web-dev-qa-db-fra.com

Méthode efficace pour générer une chaîne UUID en Java (UUID.randomUUID (). ToString () sans les tirets)

Je voudrais un utilitaire efficace pour générer des séquences uniques d'octets. UUID est un bon candidat mais UUID.randomUUID().toString() génère des éléments tels que 44e128a5-ac7a-4c9a-be4c-224b6bf81b20, qui sont utiles tant que vous n'avez pas besoin de les transmettre via HTTP. Dans ce cas, les tirets doivent être supprimés.

Je cherche un moyen efficace de générer des chaînes aléatoires, uniquement à partir de caractères alphanumériques (sans tirets ni autres symboles spéciaux).

107
Maxim Veksler

A fini par écrire quelque chose de mon propre basé sur l'implémentation UUID.Java. Notez que je ne génère pas d’UUID , mais une chaîne hexagonale aléatoire de 32 octets de la manière la plus efficace que je puisse imaginer.

La mise en oeuvre

import Java.security.SecureRandom;
import Java.util.UUID;

public class RandomUtil {
    // Maxim: Copied from UUID implementation :)
    private static volatile SecureRandom numberGenerator = null;
    private static final long MSB = 0x8000000000000000L;

    public static String unique() {
        SecureRandom ng = numberGenerator;
        if (ng == null) {
            numberGenerator = ng = new SecureRandom();
        }

        return Long.toHexString(MSB | ng.nextLong()) + Long.toHexString(MSB | ng.nextLong());
    }       
}

Usage

RandomUtil.unique()

Des tests

Certaines des entrées que j'ai testées pour s'assurer que cela fonctionne:

public static void main(String[] args) {
    System.out.println(UUID.randomUUID().toString());
    System.out.println(RandomUtil.unique());

    System.out.println();
    System.out.println(Long.toHexString(0x8000000000000000L |21));
    System.out.println(Long.toBinaryString(0x8000000000000000L |21));
    System.out.println(Long.toHexString(Long.MAX_VALUE + 1));
}
10
Maxim Veksler

Cela le fait:

public static void main(String[] args) {
    final String uuid = UUID.randomUUID().toString().replace("-", "");
    System.out.println("uuid = " + uuid);
}
197
Steve McLeod

Les tirets ne doivent pas être supprimés de la requête HTTP comme vous pouvez le voir dans l'URL de ce fil . Mais si vous voulez préparer une URL bien formée sans dépendance des données, vous devez utiliser URLEncoder.encode (chaîne de données, encodage de chaîne). ) au lieu de changer la forme standard de vos données . Pour les UUID, la représentation des chaînes est normale.

27
Donz

J'ai utilisé JUG (Java UUID Generator) pour générer un identifiant unique. Il est unique parmi les machines virtuelles. Assez bon à utiliser. Voici le code pour votre référence:

private static final SecureRandom secureRandom = new SecureRandom();
private static final UUIDGenerator generator = UUIDGenerator.getInstance();

public synchronized static String generateUniqueId() {
  UUID uuid = generator.generateRandomBasedUUID(secureRandom);

  return uuid.toString().replaceAll("-", "").toUpperCase();
}

Vous pouvez télécharger la bibliothèque à partir de: https://github.com/cowtowncoder/Java-uuid-generator

10
Sheng Chien

Je suis étonné de voir autant de chaînes remplacer les idées de UUID. Que dis-tu de ça:

UUID temp = UUID.randomUUID();
String uuidString = Long.toHexString(temp.getMostSignificantBits())
     + Long.toHexString(temp.getLeastSignificantBits());

C’est le moyen le plus rapide de le faire puisque tout le toString () de l’UUID est déjà plus cher, sans parler de l’expression régulière qui doit être analysée et exécutée ou du remplacement par une chaîne vide.

6
Stephan

Une solution simple est

UUID.randomUUID().toString().replace("-", "")

(Comme les solutions existantes, cela signifie uniquement que cela évite l'appel String # replaceAll . Le remplacement d'une expression régulière n'est pas nécessaire ici. Par conséquent, String # replace semble plus naturel, même si techniquement, il est toujours implémenté avec des expressions régulières. Étant donné que la génération de l'UUID est plus coûteuse que le remplacement, il ne devrait pas y avoir de différence significative dans le temps d'exécution.)

L'utilisation de la classe UUID est probablement assez rapide pour la plupart des scénarios, même si je m'attendrais à ce qu'une variante spécialisée manuscrite, ne nécessitant pas de post-traitement, soit plus rapide. Quoi qu'il en soit, le goulot d'étranglement du calcul global sera normalement le générateur de nombres aléatoires. Dans le cas de la classe UUID, il utilise SecureRandom .

Le générateur de nombres aléatoires à utiliser est également un compromis qui dépend de l'application. Si la sécurité l'exige, SecureRandom est en général la recommandation. Sinon, ThreadLocalRandom est une alternative (plus rapide que SecureRandom ou l'ancien Random , mais pas cryptographiquement sécurisée).

2
Philipp Claßen

J'utilise org.Apache.commons.codec.binary.Base64 pour convertir un UUID en chaîne unique sécurisée par une URL d'une longueur de 22 caractères et possédant la même unicité qu'un UUID. 

J'ai posté mon code sur Stockage de l'UUID en tant que base64 String

0
stikkos