it-swarm.com.de

Effiziente Methode zum Generieren einer UUID-Zeichenfolge in Java (UUID.randomUUID (). ToString () ohne Bindestriche)

Ich möchte ein effizientes Dienstprogramm zum Erzeugen eindeutiger Byte-Sequenzen. UUID ist ein guter Kandidat, aber UUID.randomUUID().toString() generiert Dinge wie 44e128a5-ac7a-4c9a-be4c-224b6bf81b20, was gut ist, solange Sie es nicht über HTTP übertragen müssen. In diesem Fall müssen die Bindestriche entfernt werden.

Ich suche nach einer effizienten Methode, um zufällige Zeichenfolgen nur aus alphanumerischen Zeichen zu generieren (keine Bindestriche oder andere Sonderzeichen).

107
Maxim Veksler

Am Ende habe ich selbst etwas geschrieben, basierend auf der UUID.Java-Implementierung. Beachten Sie, dass ich keine UUID generiere , sondern nur eine zufällige 32-Byte-Hex-Zeichenkette auf die effizienteste Art und Weise, die ich mir vorstellen kann.

Implementierung

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());
    }       
}

Verwendungszweck

RandomUtil.unique()

Tests

Einige der Eingaben, die ich getestet habe, um sicherzustellen, dass es funktioniert:

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

Das macht es:

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

Bindestriche müssen nicht aus der HTTP-Anforderung entfernt werden, wie Sie in der URL dieses Threads sehen können. Wenn Sie jedoch eine gut geformte URL ohne Abhängigkeit von Daten vorbereiten möchten, sollten Sie URLEncoder.encode (String-Daten, String-Codierung) verwenden ), anstatt die Standardform Ihrer Daten zu ändern. Für die Darstellung der UUID-Zeichenfolge sind Striche normal.

27
Donz

Ich habe JUG (Java UUID Generator) verwendet, um eine eindeutige ID zu generieren. Es ist in allen JVMs eindeutig. Ziemlich gut zu gebrauchen. Hier ist der Code für Ihre Referenz:

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();
}

Sie können die Bibliothek unter folgender Adresse herunterladen: https://github.com/cowtowncoder/Java-uuid-generator

10
Sheng Chien

Ich bin erstaunt, dass so viele Saiten die UUID-Ideen ersetzen. Wie wäre es damit:

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

Dies ist der schnellste Weg, dies zu tun, da das gesamte toString () von UUID bereits teurer ist, ganz zu schweigen von dem regulären Ausdruck, der geparst und ausgeführt werden muss, oder dem Ersetzen mit leerem String.

6
Stephan

Eine einfache Lösung ist

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

(Wie bei den vorhandenen Lösungen, nur dass der String # replaceAll call vermieden wird.) Das Ersetzen von regulären Ausdrücken ist hier nicht erforderlich. Daher fühlt sich String # replace natürlicher an, obwohl es technisch immer noch mit regulären Ausdrücken implementiert ist. Da die Generierung der UUID teurer ist als die Ersetzung, sollte die Laufzeit nicht signifikant voneinander abweichen.)

Die Verwendung der UUID-Klasse ist für die meisten Szenarien wahrscheinlich schnell genug. Allerdings würde ich davon ausgehen, dass einige spezielle handschriftliche Varianten, die keine Nachbearbeitung benötigen, schneller sind. Der Engpass der Gesamtberechnung ist normalerweise der Zufallszahlengenerator. Im Falle der UUID-Klasse verwendet sie SecureRandom .

Welcher Zufallszahlengenerator verwendet wird, hängt auch von der Anwendung ab. Wenn es auf die Sicherheit ankommt, ist SecureRandom im Allgemeinen die Empfehlung. Andernfalls ist ThreadLocalRandom eine Alternative (schneller als SecureRandom oder das alte Random , jedoch nicht kryptographisch sicher).

2
Philipp Claßen

Ich habe gerade die UUID toString () -Methode kopiert und sie aktualisiert, um "-" daraus zu entfernen. Es wird viel schneller und unkomplizierter sein als jede andere Lösung

public String generateUUIDString(UUID uuid) {
    return (digits(uuid.getMostSignificantBits() >> 32, 8) +
            digits(uuid.getMostSignificantBits() >> 16, 4) +
            digits(uuid.getMostSignificantBits(), 4) +
            digits(uuid.getLeastSignificantBits() >> 48, 4) +
            digits(uuid.getLeastSignificantBits(), 12));
}

/** Returns val represented by the specified number of hex digits. */
private String digits(long val, int digits) {
    long hi = 1L << (digits * 4);
    return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}

Verwendungszweck:

generateUUIDString(UUID.randomUUID())

Eine weitere Implementierung unter Verwendung von Reflection

public String generateString(UUID uuid) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

    if (uuid == null) {
        return "";
    }

    Method digits = UUID.class.getDeclaredMethod("digits", long.class, int.class);
    digits.setAccessible(true);

    return ( (String) digits.invoke(uuid, uuid.getMostSignificantBits() >> 32, 8) +
            digits.invoke(uuid, uuid.getMostSignificantBits() >> 16, 4) +
            digits.invoke(uuid, uuid.getMostSignificantBits(), 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits() >> 48, 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits(), 12));

}
1
Ravi Desai

Ich verwende org.Apache.commons.codec.binary.Base64, um eine UUID in eine URL-sichere eindeutige Zeichenfolge zu konvertieren, die 22 Zeichen lang ist und dieselbe Eindeutigkeit wie die UUID aufweist. 

Ich habe meinen Code auf UUID als base64-String gespeichert

0
stikkos