web-dev-qa-db-fra.com

Comment générer un Long positif unique en utilisant UUID

J'ai besoin de générer des identifiants longs uniques pour ma colonne de clé primaire de base de données.

Je pensais que je pouvais utiliser ID.randomUUID (). GetMostSignificantBits () mais parfois, cela générait également des longs négatifs, ce qui est un problème pour moi.

Est-il possible de générer uniquement des valeurs positives à partir de l'UUID? Il y aura comme des milliards d'entrées, donc je veux que chaque clé générée soit unique.

28
Saurabh Kumar

Jetez un œil à http://commons.Apache.org/sandbox/commons-id//index.html Il a un LongGenerator qui peut vous donner exactement ce dont vous avez besoin.

De plus, si vous utilisez Hibernate, vous pouvez lui demander de générer des ID pour vous (il a plusieurs algorithmes parmi lesquels vous pouvez choisir), sinon vous pouvez simplement jeter un œil à leur implémentation par exemple 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

La raison pour laquelle cela fonctionne est que lorsque vous faites au niveau du bit et avec 1, il permet au même chiffre de passer tel quel et lorsque vous le faites au niveau du bit et avec 0, il le bloque et le résultat est 0. Maintenant, Long.MAX_Value en binaire est

0111111111111111111111111111111111111111111111111111111111111111 

c'est 0 suivi de 63 1s (le total est de 64 bits, c'est long en Java)

Donc, lorsque vous binaire et un nombre X avec ce nombre ci-dessus, vous obtiendrez le même nombre X, sauf que le bit le plus à gauche est maintenant transformé en zéro. Ce qui signifie que vous avez seulement changé le signe de ce nombre et non la valeur.

28
Sasha Pechenyi

Comme les autres l'ont écrit, long n'a pas assez d'espace pour un numéro unique. Mais dans de nombreux cas, un nombre peut être suffisamment unique pour une utilisation spécifique. Par exemple, un horodatage avec une précision en nanosecondes est souvent suffisant. Pour l'obtenir, décalez les millisecondes actuelles de 20 bits à gauche pour allouer de l'espace aux nanosecondes, puis superposez-le avec les nanosecondes:

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

La partie nano & ~ 9223372036854251520L prend les nanosecondes actuelles et définit les 44 premiers octets à 0, ne laissant que les 20 bons bits qui représentent les nanosecondes jusqu'à une milliseconde (999999 nanos). C'est la même chose que:

nanoseconds & ~1111111111111111111111111111111111111111111100000000000000000000

Remarque: les nanosecondes ne doivent pas être utilisées pour représenter l'heure actuelle car leur point de départ n'est pas fixe dans le temps et parce qu'elles sont recyclées lorsqu'elles atteignent le maximum.

Vous pouvez utiliser n'importe quelle autre manipulation de bits. Il est généralement bon de prendre en compte l'heure actuelle et quelque chose d'autre comme l'ID de thread actuel, l'ID de processus, l'IP.

8
Daniel Nuriyev

Je viens de tomber sur cette solution. J'essaie pour l'instant de comprendre la solution. Elle dit Java implémentation de Twitter snowflake. Générateur d'ID séquentiel 64 bits basé sur l'algorithme de génération d'ID Twitter snowflake.

https://github.com/Predictor/javasnowflake

Toutes suggestions sont les bienvenues.

2
Saurabh Kumar