Effiziente Methode zum Generieren von UUID-Strings in Java (UUID.randomUUID().toString() ohne Bindestriche)

Lesezeit: 7 Minuten

Benutzer-Avatar
Maxim Weksler

Ich möchte ein effizientes Dienstprogramm, um eindeutige Folgen von Bytes zu generieren. UUID ist ein guter Kandidat, aber UUID.randomUUID().toString() erzeugt Sachen wie 44e128a5-ac7a-4c9a-be4c-224b6bf81b20 was gut ist, aber ich würde eine strichlose Saite bevorzugen.

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

  • Warum müssen die Bindestriche entfernt werden, damit eine solche UUID über HTTP übertragen werden kann?

    – Bruno

    27. September 2010 um 14:08 Uhr


  • Ich dachte nicht, dass Bindestriche in HTTP im Allgemeinen entfernt werden müssten … welches Bit verursacht Ihnen Ärger?

    – Jon Skeet

    27. September 2010 um 14:08 Uhr

  • Vielleicht ist es in einer mobilen Umgebung, wenn Sie immer noch für jedes übertragene Byte bezahlen und ein Netzwerk mit niedriger Bandbreite und hoher Latenz verwenden, in einigen Szenarien immer noch wichtig, 4 Bytes zu sparen …

    – Guido

    27. September 2010 um 14:36 ​​Uhr

  • Ich möchte, dass die Bindestriche entfernt werden, da wir später die UUID-Zeichenfolge als eindeutige Anforderungskennung verwenden. Es ist dann viel einfacher, nur mit Hexadezimalzeichen zu arbeiten [a-f0-9-].

    – Maxim Weksler

    28. September 2010 um 10:19 Uhr

  • Ich habe den HTTP-Teil entfernt, weil er nicht relevant ist (wie Maxim erklärte) und die Leser nur verwirrt (wie sowohl in den Kommentaren als auch in den Antworten zu sehen ist).

    – Ondra Žižka

    13. Februar 2020 um 16:11 Uhr


Benutzer-Avatar
Steve McLeod

Das geht:

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

  • Beispielsweise verwendet Mongodb keine Bindestriche in ObjectID. Daher kann das Entfernen von Bindestrichen für API nützlich sein.

    – Alexej Rjaschskich

    28. März 2015 um 13:28 Uhr

  • Ich nenne Ihnen einen Grund dafür. Es gibt eine API, mit der ich arbeite (hochkarätig, bekannt), die keine Bindestriche in ihrer UUID zulässt. Du musst sie ausziehen.

    – Michael Gaines

    28. Oktober 2015 um 3:28 Uhr

  • Es ist nicht erforderlich, replaceAll auszuführen, da dies reguläre Ausdrücke verwendet. Mach einfach .replace(“-“, “”)

    – Craigo

    31. Mai 2016 um 8:50 Uhr

  • Die Methode replace der Klasse String ist meiner Meinung nach etwas langsam

    – bmscomp

    20. August 2019 um 15:22 Uhr

  • @bmscomp für den ersten Aufruf ist es langsam, aber für die nächsten Aufrufe gibt es kein Problem.

    – Gaurav

    28. August 2019 um 8:57 Uhr

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

  • “Bindestriche müssen nicht aus der HTTP-Anfrage entfernt werden, wie Sie in der URL dieses Threads sehen können.” Verstehen Sie nicht, es sei denn, Stack Overflow hat zuvor UUIDs in ihren URLs verwendet?

    – RenniePet

    17. September 2014 um 13:17 Uhr

  • Nicht, dass die URL eine UUID ist, sondern dass sie Bindestriche enthält: http://stackoverflow.com/questions/3804591/efficient-method-to-generate-uuid-string-in-java-uuid-randomuuid-tostring-w?rq=1

    – Octavia Togami

    22. November 2014 um 5:52 Uhr

Benutzer-Avatar
Sheng-Chien

Ich habe JUG (Java UUID Generator) verwendet, um eine eindeutige ID zu generieren. Es ist über JVMs hinweg einzigartig. 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 herunterladen von: https://github.com/cowtowncoder/java-uuid-generator

  • Was ist für Ihren Fall falsch mit UUID.randomUUID().toString() ? Beachten Sie auch, dass Sie (theoretisch) die Entropie verringern, indem Sie ein statisches finales SecureRandom halten (es flüchtig machen). warum auch die generateUniqueId synchronisieren? Dies bedeutet, dass alle Ihre Threads bei dieser Methode blockiert sind.

    – Maxim Weksler

    28. September 2010 um 10:27 Uhr

  • Zunächst einmal behauptet Safehaus, JUG sei schneller. Und es kann maschinenübergreifend eindeutige IDs generieren, die Sie möglicherweise nicht benötigen. Sie haben eine zeitbasierte Methode, die unter allen Methoden die schickste ist. Ja, eine Synchronisierung ist hier nicht erforderlich, da ich festgestellt habe, dass SecureRandom bereits Thread-sicher ist. Warum würde das Deklarieren von static final auf SecureRandom die Entropie verringern? Ich bin gespannt 🙂 Mehr Details gibt es hier: jug.safehaus.org/FAQ

    – Sheng-Chien

    28. September 2010 um 14:46 Uhr


  • JUG kann auch auf Zufallszahlen basierende UUIDs generieren; Aber die Hauptgründe, warum Entwickler die zeitbasierte Variante bevorzugen, sind entweder, dass sie 10-20x schneller ist (cowtowncoder.com/blog/archives/2010/10/entry_429.html); oder dass sie dem Zufall nicht vertrauen, um eindeutige IDs zu erzeugen (was irgendwie lustig ist)

    – StaxMan

    24. Oktober 2010 um 3:30 Uhr

  • jug.safehaus.org existiert nicht mehr, aber Sie finden die FAQ unter raw.github.com/cowtowncoder/java-uuid-generator/3.0/…

    – Daniel Serodio

    20. September 2012 um 21:58 Uhr

  • +1 für die Erwähnung von JUG – Ich habe seine Nützlichkeit überprüft, aber es ist gut zu wissen, dass es einige ernsthafte gibt java.util.UUID Alternativen.

    – Greg Dubicki

    6. September 2015 um 17:28 Uhr

Benutzer-Avatar
Maxim Weksler

Am Ende schrieb ich etwas Eigenes auf der Grundlage der UUID.java-Implementierung. Beachten Sie, dass ich bin generiert keine UUIDstattdessen nur eine zufällige 32-Byte-Hex-Zeichenfolge auf die effizienteste Weise, die ich mir vorstellen konnte.

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

Prüfungen

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

Eine einfache Lösung ist

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

(Wie die bestehenden Lösungen, nur dass es das vermeidet Zeichenkette#replaceAll Anruf. Eine Ersetzung regulärer Ausdrücke ist hier also nicht erforderlich Zeichenkette#ersetzen fühlt sich natürlicher an, obwohl es technisch immer noch mit regulären Ausdrücken implementiert wird. Da das Generieren der UUID teurer ist als das Ersetzen, sollte es keinen signifikanten Unterschied in der Laufzeit geben.)

Die Verwendung der UUID-Klasse ist wahrscheinlich für die meisten Szenarien schnell genug, obwohl ich erwarten würde, dass einige spezielle handgeschriebene Varianten, die keine Nachbearbeitung benötigen, schneller sind. Wie auch immer, der Flaschenhals der Gesamtberechnung wird normalerweise der Zufallszahlengenerator sein. Im Falle der UUID-Klasse verwendet sie SecureRandom.

Welcher Zufallszahlengenerator verwendet werden soll, ist ebenfalls ein Kompromiss, der von der Anwendung abhängt. Wenn es sicherheitsrelevant ist, ist SecureRandom im Allgemeinen die Empfehlung. Andernfalls, ThreadLocalRandom ist eine Alternative (schneller als SecureRandom oder das alte Zufälligaber nicht kryptografisch sicher).

Benutzer-Avatar
Stefan

Ich bin erstaunt, dass so viele UUID-Ersetzungsideen für Zeichenfolgen zu sehen sind. Wie wäre es damit:

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

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

Ich habe gerade die Methode UUID toString() kopiert und sie gerade aktualisiert, um “-” daraus zu entfernen. Es wird viel schneller und direkter 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, die Reflektion verwendet

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

}

1354050cookie-checkEffiziente Methode zum Generieren von UUID-Strings in Java (UUID.randomUUID().toString() ohne Bindestriche)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy