web-dev-qa-db-ja.com

UUIDを使用して一意の正のLongを生成する方法

データベースの主キー列に対して一意のロングIDを生成する必要があります。

私はID.randomUUID()。getMostSignificantBits()を使用できると思ったが、時々それが負の長さを生成することも私にとっては問題である。

UUIDから正のlongのみを生成することは可能ですか?数十億のエントリがあるので、生成された各キーは一意でなければなりません。

28
Saurabh Kumar

http://commons.Apache.org/sandbox/commons-id//index.html を見てください。必要なものを正確に提供できるLongGeneratorがあります。

さらに、Hibernateを使用している場合は、IDを生成するように要求できます(選択可能な複数のアルゴリズムがあります)。そうでない場合は、たとえば、実装を見ることができます http:// grepcode.com/file/repo1.maven.org/maven2/hibernate/hibernate/2.1.8/net/sf/hibernate/id/TableHiLoGenerator.Java#TableHiLoGenerator

7
Doron Manor
UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE

これが機能する理由は、ビット単位で&1を実行すると同じ桁をそのまま通過させ、ビット単位で&0を実行するとブロックして結果が0になるためです。

0111111111111111111111111111111111111111111111111111111111111111 

これは0であり、その後に63 1が続きます(合計は64ビットで、Javaでは長いです)

したがって、この数値でビット単位で数値Xを取得すると、左端のビットがゼロに変わることを除いて、同じ数値Xが得られます。つまり、値ではなくその数値の符号のみを変更したことになります。

28
Sasha Pechenyi

他の人が書いたように、longには一意の番号を入れるのに十分なスペースがありません。しかし、多くの場合、番号は特定の用途に対して十分に一意である場合があります。たとえば、多くの場合、ナノ秒の精度のタイムスタンプで十分です。それを取得するには、現在のミリ秒を20ビット左にシフトして、ナノ秒のスペースを割り当ててから、ナノ秒でオーバーレイします。

(System.currentTimeMillis() << 20) | (System.nanoTime() & ~9223372036854251520L);

nano&〜9223372036854251520L部分は現在のナノ秒を取り、最初の44バイトを0に設定し、ナノ秒を表す右20ビットのみを1ミリ秒(999999ナノ)まで残します。

nanoseconds & ~1111111111111111111111111111111111111111111100000000000000000000

補足事項:ナノ秒は、開始点が時間的に固定されておらず、最大値に達するとリサイクルされるため、現在の時刻を表すために使用しないでください。

他のビット操作を使用できます。通常、現在の時刻と、現在のスレッドID、プロセスID、IPなどのその他のものを考慮に入れることをお勧めします。

8
Daniel Nuriyev

このソリューションに出会ったばかりです。私はしばらくの間、ソリューションを理解しようとしています。Java Twitterスノーフレークの実装。TwitterスノーフレークID生成アルゴリズムに基づく64ビットシーケンシャルIDジェネレーター。

https://github.com/Predictor/javasnowflake

どんな提案でも大歓迎です。

2
Saurabh Kumar