2010-12-10 52 views
2

J'ai besoin de générer un nombre unique de 32 bits en Java. J'ai besoin de renvoyer le numéro en Java int, ce qui est requis par l'interface. Pouvez-vous partager quelques idées à ce sujet?Comment obtenir un nombre unique de 32 bits en Java?

Le numéro sera utilisé en tant que PK MySQL et plusieurs threads pourraient générer leur propre identifiant unique en même temps. (Désolé, il est décidé de ne pas utiliser l'identifiant incrémental MySQL)

J'ai essayé la classe UUID mais il semble que les données qu'elle génère ont plus de bits que je ne peux en utiliser.

Je trouve cela, mais pas sûr que cela fonctionne:

// seems no way to get int 
    UUID id = UUID.randomUUID(); 
    System.out.println(id); 

    // not working either? 
    java.rmi.server.UID uid = new java.rmi.server.UID(); 
    System.out.println(uid.toString()); 

    // the one i am using 
    SecureRandom prng = SecureRandom.getInstance("SHA1PRNG"); 
    prng.setSeed(System.currentTimeMillis()); 
    int ret = prng.nextInt(); 
    System.out.println(ret); 
+0

duplication possible de [générer UUID mais seulement pour 8 caractères] (http://stackoverflow.com/questions/4267475/generating-uuid-but-only-for-8-characters) –

+1

Le type MySQL 'bigint' est 64 bits et aurait moins de chance de collision. Ce serait mieux si vous pouvez changer le schéma de la base de données. –

Répondre

5

Comment "unique" êtes-vous vouloir? En bref, quel est le domaine de collision? Si vous traitez des milliers de clés alors Random.nextInt() fait exactement ce que vous voulez par rapport à ce que vous avez essayé avec les UUID de la version 4 (UUID v4 génère 128 bits aléatoires).

Si vous avez besoin de quelque chose avec moins de chance de collision, vous devez avoir un nombre entier incrémenté globalement mais il y a beaucoup de précautions à prendre ici, comme garder l'état entre les démarrages de la JVM. Pour cela, vous devriez regarder dans AtomicIntegers.

+0

Je suis plus clair pour les exigences; il semble qu'il n'y ait pas vraiment besoin d'être «très unique». Nous avons décidé d'utiliser des valeurs basées sur le temps et de gérer les courses nous-mêmes. Cependant, cette discussion est utile et je vous remercie tous. –

0

L'approche SecureRandom est très bien, mais ne fixe pas la graine sur elle. Il choisira sa propre graine d'une manière (probablement) sécurisée.

Vous pouvez également utiliser un UUID et simplement jeter les bits dont vous n'avez pas besoin, par ex.

int key = (int)UUID.randomUUID().getLeastSignificantBits(); 

EDIT: Vous devez également savoir que le SecureRandom est nettement plus lent que Random. Puisque vous ne faites pas de chiffrement ici, pourquoi ne pas utiliser Random?

+1

Non, vous ne pourriez pas. http://blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx – dan04

+0

La source de la classe UUID montre qu'elle génère 128 bits aléatoires, puis bricole avec quelques-uns d'entre eux. Les bits modifiés sont tous dans l'ensemble le plus significatif, donc prendre seulement les bits les moins significatifs devrait fonctionner correctement. Pourtant, c'est moins de travail d'utiliser simplement un 'Random'. –

+0

@ dan04: Pour l'implémentation UUID, vous avez raison, mais pour l'implémentation Java UUID (au moins l'implémentation de Sun Java 6) ma réponse fonctionnera correctement. –

0

Je pense que vous pouvez utiliser une fonction de hachage 32 bits. détails dans le tutoriel suivant http://www.concentric.net/~ttwang/tech/inthash.htm

private static int hash(int key){ 

      key = ~key + (key << 15); // key = (key << 15) - key - 1; 
      key = key^(key >>> 12); 
      key = key + (key << 2); 
      key = key^(key >>> 4); 
      key = key * 2057; // key = (key + (key << 3)) + (key << 11); 
      key = key^(key >>> 16); 
      return key; 

    }