4

さて、私はJavaコードでUIDを生成する方法を検討してきました(それらのほとんどはstackoverflowにも来ています)。タイムスタンプを使用するため、Java の UUID を使用して一意の ID を作成するのが最善です。しかし、私の問題は、それが 128 ビットの長さであり、14 または 15 文字のような短い文字列が必要なことです。そこで、そのために次のコードを考案しました。

Date date = new Date();
Long luid = (Long) date.getTime();
String suid = luid.toString();
System.out.println(suid+": "+suid.length() + " characters");

Random rn = new Random();
Integer long1 = rn.nextInt(9);
Integer long2 = rn.nextInt(13);

String newstr = suid.substring(0, long2) + " " + long1 + " " + suid.subtring(long2);
System.out.println("New string in spaced format: "+newstr);
System.out.println("New string in proper format: "+newstr.replaceAll(" ", ""));

元の文字列のみと比較するために、間隔を空けて適切にフォーマットされた文字列を表示しているだけであることに注意してください。

これにより、毎回 100% の一意の ID が保証されますか? それとも、数字が繰り返される可能性があると思いますか? また、乱数をランダムな位置に挿入して重複した数字を作成する代わりに、最初または最後に挿入することもできます。これは、私の UID の必要な長さを完成させるためのものです。ただし、13 文字未満の UID が必要な場合、これはおそらく機能しない可能性があります。

何かご意見は?

4

2 に答える 2

3

もちろんこれが分散システムならうまくいきませんが、以下のようなものはどうでしょうか。

private AtomicLong uniqueId = new AtomicLong(0);
...
// get a unique current-time-millis value 
long now;
long prev;
do {
    prev = uniqueId.get();
    now = System.currentTimeMillis();
    // make sure now is moving ahead and unique
    if (now <= prev) {
        now = prev + 1;
    }
    // loop if someone else has updated the id
} while (!uniqueId.compareAndSet(prev, now));

// shuffle it
long result = shuffleBits(now);
System.out.println("Result is " + Long.toHexString(result));

public static long shuffleBits(long val) {
    long result = 0;
    result |= (val & 0xFF00000000000000L) >> 56;
    result |= (val & 0x00FF000000000000L) >> 40;
    result |= (val & 0x0000FF0000000000L) >> 24;
    result |= (val & 0x000000FF00000000L) >> 8;
    result |= (val & 0x00000000FF000000L) << 8;
    result |= (val & 0x0000000000FF0000L) << 24;
    result |= (val & 0x000000000000FF00L) << 40;
    result |= (val & 0x00000000000000FFL) << 56;
    return result;
}

ビットシャッフルを改善して、反復ごとに値の変化を増やすことができます。数字を連続させたくないとおっしゃいましたが、完全なランダム性の要件を指定していませんでした。

確かに ほど良くはありませんUUIDが、データベース操作よりも高速です。

于 2011-11-16T02:40:45.987 に答える
1

簡単な方法は、データベース シーケンスが利用可能な場合はそれを使用することです。そうでない場合は、次のようにシミュレートできます。

  1. これまでに使用された最大値 (最初は 0) を保持する列を持つテーブルを作成します。一部のアプリケーションでは、各行が特定の一意の ID を制御する複数の行を作成しますが、実際に必要なのは 1 つの行だけです。この例では、テーブル構造が次のようになっていると想定しています。

    ID_TABLE
    ID_NAME    VARCHAR(40); -- Or whatever type is appropriate
    ID_COLUMN  INTEGER; -- Or whatever type is appropriate
    
  2. 各プロセスは、次のようにして行を予約します。

    a. Begin Txn;
    b. Update ID_TABLE set ID_VALUE = ID_VALUE + <n> where ID_NAME = <name>;     
    c. Select ID_VALUE from ID_TABLE where ID_NAME = <name>;  
    d. Commit Txn;
    

    これがすべて正常に完了すると、(val - n + 1) から val までの範囲が予約されたことになります。ここで、val は手順 c から返された値です。その上。

  3. 各プロセスは、予約した範囲から ID を配布します。プロセスがマルチスレッドの場合、同期を提供して、各値が最大 1 回渡されるようにする必要があります。値の供給を使い果たすと、ステップ 2 に戻り、さらに値を予約します。予約されているすべての値の使用が保証されているわけではないことに注意してください。予約したすべての値を使用せずにプロセスが終了すると、未使用の値は失われ、使用されなくなります。

于 2011-11-13T03:36:51.793 に答える