Crear un GUID/UUID en Java

13 minutos de lectura

Avatar de usuario de Chris Dutrow
chris dutrow

¿Cuáles son algunas de las mejores formas de crear un GUID/UUID en Java?

  • La pregunta en stackoverflow.com/questions/325443/generate-uuid-in-java es más sobre las colisiones de GUID, luego cómo es el equivalente de un GUID en la pila de tecnología de Java, que es lo que (creo) es más el foco de esta pregunta.

    – Jon Adams

    18/10/2012 a las 15:48

java.util.UUID.randomUUID();

  • ¿podría volver a repetir? porque Guid nunca va a repetir

    – ángel

    7 de agosto de 2013 a las 14:13

  • @angel Sí, es teóricamente posible para el UUID.randomUUID método para devolver un duplicado, pero esto es no es en absoluto una preocupación realista. La implementación de Oracle/OpenJDK utiliza un generador de números aleatorios criptográficamente fuerte. Dado eso, y dada la rango astronómico dado por tantos bits en un UUID, puede generar muchos millones de dichos valores en su aplicación y aún así dormir bien. El uso de una de las otras variantes reduce aún más la posibilidad de colisiones incluso más cerca de cero debido al uso de “espacio y tiempo”, [1] dirección MAC o nombre, y [2] fecha-hora actual, como restricciones.

    – Basil Bourque

    16 de julio de 2015 a las 21:28


  • @RenniePet Eh, si eres tan paranoico y obtuviste acceso a la lista de identificaciones ya utilizadas al crear una nueva, solo generas nuevas en un while hasta que tengas uno que no esta dentro de tu lista :p

    – Nyerguds

    5 de julio de 2016 a las 13:11

  • El generador de números aleatorios criptográficos de Oracle suele ser un PRNG con una semilla aleatoria. La semilla aleatoria generalmente se obtiene utilizando una fuente de “entropía” proporcionada por el sistema operativo. Si puede degradar o comprometer esa fuente, entonces aumenta la probabilidad de que un generador de números aleatorios criptográficos produzca el mismo número. También vale la pena señalar que en algunas plataformas (por ejemplo, virtualizadas), el sistema operativo puede quedarse sin entropía. Hay “trucos dudosos” para solucionar esto, pero implican degradar la calidad de la entropía.

    – Esteban C.

    14 de septiembre de 2017 a las 1:27

  • Esto no es solo una preocupación académica. he visto un (sin verificar !!) afirmar que alguien hizo tiene problemas con los UUID aleatorios que no son únicos.

    – Esteban C.

    14 de septiembre de 2017 a las 1:29

Avatar de usuario de Mark Byers
marca byers

Echa un vistazo a la clase UUID incluido con Java 5 y versiones posteriores.

Por ejemplo:

  • Si incluye un ejemplo como lo hizo Kaleb Brasee, su buena respuesta sería aún mejor.

    – cero3

    11 de enero de 2016 a las 9:29

  • Funciona en AndroidStudio 2.3 y en los niveles de API 21 y superiores al menos. Tal vez más atrás también.

    – Raddevus

    12 mayo 2017 a las 20:04

  • TL;DR… ” UUID uuid = UUID.randomUUID(); “

    – Aviram Fireberger

    13 de agosto de 2018 a las 12:22

Avatar de usuario de Anton Belev
Antón Belev

Solo para extender la respuesta de Mark Byers con un ejemplo:

import java.util.UUID;

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

  • Votado negativo porque no se proporcionan “versiones extendidas” de JSF, Spring MVC, Android y Swing. Vamos, ¿por qué proporcionar “respuestas” como esta?

    – terrorrussia-sigue-matando

    24 de diciembre de 2021 a las 8:11

  • @fluffy y ¿dónde exactamente se pidió esto en la pregunta?

    – Antón Belev

    24 de diciembre de 2021 a las 14:17

Avatar de usuario de Stephen C
esteban c

Depende de que tipo de UUID quieres.

  • El Java estándar UUID la clase genera Versión 4 (aleatorios) UUID. (ACTUALIZARVersión 3 (nombre) También se pueden generar UUID). También puede manejar otras variantes, aunque no puede generarlas. (En este caso, “manejar” significa construir UUID instancias de long, byte[] o String representaciones, y proporcionar algunos accesores apropiados.)

  • El Generador de UUID de Java (JUG) La implementación pretende admitir “los 3 tipos ‘oficiales’ de UUID según lo definido por RFC-4122“… aunque el RFC en realidad define 4 tipos y menciona un quinto tipo.

Para obtener más información sobre los tipos y variantes de UUID, hay un buen resumen en Wikipediay los detalles sangrientos están en RFC 4122 y las demás especificaciones.

Avatar de usuario de Basil Bourque
albahaca bourque

Las otras respuestas son correctas, especialmente esta de Stephen C.

Llegar fuera de Java

Generando un UUID el valor dentro de Java está limitado a Versión 4 (aleatoria) por motivos de seguridad.

Si desea otras versiones de UUID, una vía es hacer que su aplicación Java llegue fuera del JVM para generar UUID llamando a:

  • Utilidad de línea de comandos
    Incluido con casi todos los sistemas operativos.
    Por ejemplo, uuidgen se encuentra en Mac OS X, BSD y Linux.
  • Servidor de base de datos
    Usar JDBC para recuperar un UUID generado en el servidor de la base de datos.
    por ejemplo, el uuid-ossp extensión a menudo incluida con postgres. Esa extensión puede generar valores de las versiones 1, 3 y 4 y, además, un par de variaciones:
  • uuid_generate_v1mc() – genera un UUID de versión 1 pero usa una dirección MAC de multidifusión aleatoria en lugar de la dirección MAC real de la computadora.
  • uuid_generate_v5(namespace uuid, name text) – genera un UUID de la versión 5, que funciona como un UUID de la versión 3, excepto que SHA-1 se usa como método hash.
  • Servicio web
    Por ejemplo, Generador de UUID crea las versiones 1 y 3, así como valores nulos y GUID.

  • Tengo algunos problemas con su respuesta: primero, ya se demostró que era incorrecto que solo puede obtener V4 de la biblioteca estándar de Java (también es posible V3). En segundo lugar, hace que parezca que no hay opciones dentro de Java además de la biblioteca estándar, junto con un ondulado manual “debido a problemas de seguridad”. Y por último, generalmente es ineficiente (programación y/o rendimiento) comenzar a depender de fuentes externas cuando hay muchas formas de hacerlo dentro de Java (a menos que lo necesite, por supuesto, por ejemplo, como parte de la creación de un registro en el servidor SQL).

    – DennisK

    6 de febrero de 2018 a las 9:25


Esta respuesta contiene 2 generadores para UUID aleatorios y basados ​​en nombres, que cumplen con RFC-4122. Siéntete libre de usar y compartir.

ALEATORIO (v4)

Esta clase de utilidad que genera UUID aleatorios:

package your.package.name;

import java.security.SecureRandom;
import java.util.Random;
import java.util.UUID;

/**
 * Utility class that creates random-based UUIDs.
 * 
 */
public abstract class RandomUuidCreator {

    private static final int RANDOM_VERSION = 4;

    /**
     * Returns a random-based UUID.
     * 
     * It uses a thread local {@link SecureRandom}.
     * 
     * @return a random-based UUID
     */
    public static UUID getRandomUuid() {
        return getRandomUuid(SecureRandomLazyHolder.THREAD_LOCAL_RANDOM.get());
    }

    /**
     * Returns a random-based UUID.
     * 
     * It uses any instance of {@link Random}.
     * 
     * @return a random-based UUID
     */
    public static UUID getRandomUuid(Random random) {

        long msb = 0;
        long lsb = 0;

        // (3) set all bit randomly
        if (random instanceof SecureRandom) {
            // Faster for instances of SecureRandom
            final byte[] bytes = new byte[16];
            random.nextBytes(bytes);
            msb = toNumber(bytes, 0, 8); // first 8 bytes for MSB
            lsb = toNumber(bytes, 8, 16); // last 8 bytes for LSB
        } else {
            msb = random.nextLong(); // first 8 bytes for MSB
            lsb = random.nextLong(); // last 8 bytes for LSB
        }

        // Apply version and variant bits (required for RFC-4122 compliance)
        msb = (msb & 0xffffffffffff0fffL) | (RANDOM_VERSION & 0x0f) << 12; // apply version bits
        lsb = (lsb & 0x3fffffffffffffffL) | 0x8000000000000000L; // apply variant bits

        // Return the UUID
        return new UUID(msb, lsb);
    }

    private static long toNumber(final byte[] bytes, final int start, final int length) {
        long result = 0;
        for (int i = start; i < length; i++) {
            result = (result << 8) | (bytes[i] & 0xff);
        }
        return result;
    }

    // Holds thread local secure random
    private static class SecureRandomLazyHolder {
        static final ThreadLocal<Random> THREAD_LOCAL_RANDOM = ThreadLocal.withInitial(SecureRandom::new);
    }

    /**
     * For tests!
     */
    public static void main(String[] args) {

        System.out.println("// Using thread local `java.security.SecureRandom` (DEFAULT)");
        System.out.println("RandomUuidCreator.getRandomUuid()");
        System.out.println();
        for (int i = 0; i < 5; i++) {
            System.out.println(RandomUuidCreator.getRandomUuid());
        }

        System.out.println();
        System.out.println("// Using `java.util.Random` (FASTER)");
        System.out.println("RandomUuidCreator.getRandomUuid(new Random())");
        System.out.println();
        Random random = new Random();
        for (int i = 0; i < 5; i++) {
            System.out.println(RandomUuidCreator.getRandomUuid(random));
        }
    }
}

Esta es la salida:

// Using thread local `java.security.SecureRandom` (DEFAULT)
RandomUuidCreator.getRandomUuid()

'ef4f5ad2-8147-46cb-8389-c2b8c3ef6b10'
'adc0305a-df29-4f08-9d73-800fde2048f0'
'4b794b59-bff8-4013-b656-5d34c33f4ce3'
'22517093-ee24-4120-96a5-ecee943992d1'
'899fb1fb-3e3d-4026-85a8-8a2d274a10cb'

// Using `java.util.Random` (FASTER)
RandomUuidCreator.getRandomUuid(new Random())

'4dabbbc2-fcb2-4074-a91c-5e2977a5bbf8'
'078ec231-88bc-4d74-9774-96c0b820ceda'
'726638fa-69a6-4a18-b09f-5fd2a708059b'
'15616ebe-1dfd-4f5c-b2ed-cea0ac1ad823'
'affa31ad-5e55-4cde-8232-cddd4931923a'

BASADO EN NOMBRE (v3 y v5)

Esta clase de utilidad que genera UUID basados ​​en nombres (MD5 y SHA1):

package your.package.name;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
 * Utility class that creates UUIDv3 (MD5) and UUIDv5 (SHA1).
 *
 */
public class HashUuidCreator {

    // Domain Name System
    public static final UUID NAMESPACE_DNS = new UUID(0x6ba7b8109dad11d1L, 0x80b400c04fd430c8L);
    // Uniform Resource Locator
    public static final UUID NAMESPACE_URL = new UUID(0x6ba7b8119dad11d1L, 0x80b400c04fd430c8L);
    // ISO Object ID
    public static final UUID NAMESPACE_ISO_OID = new UUID(0x6ba7b8129dad11d1L, 0x80b400c04fd430c8L);
    // X.500 Distinguished Name
    public static final UUID NAMESPACE_X500_DN = new UUID(0x6ba7b8149dad11d1L, 0x80b400c04fd430c8L);

    private static final int VERSION_3 = 3; // UUIDv3 MD5
    private static final int VERSION_5 = 5; // UUIDv5 SHA1

    private static final String MESSAGE_DIGEST_MD5 = "MD5"; // UUIDv3
    private static final String MESSAGE_DIGEST_SHA1 = "SHA-1"; // UUIDv5

    private static UUID getHashUuid(UUID namespace, String name, String algorithm, int version) {

        final byte[] hash;
        final MessageDigest hasher;

        try {
            // Instantiate a message digest for the chosen algorithm
            hasher = MessageDigest.getInstance(algorithm);

            // Insert name space if NOT NULL
            if (namespace != null) {
                hasher.update(toBytes(namespace.getMostSignificantBits()));
                hasher.update(toBytes(namespace.getLeastSignificantBits()));
            }

            // Generate the hash
            hash = hasher.digest(name.getBytes(StandardCharsets.UTF_8));

            // Split the hash into two parts: MSB and LSB
            long msb = toNumber(hash, 0, 8); // first 8 bytes for MSB
            long lsb = toNumber(hash, 8, 16); // last 8 bytes for LSB

            // Apply version and variant bits (required for RFC-4122 compliance)
            msb = (msb & 0xffffffffffff0fffL) | (version & 0x0f) << 12; // apply version bits
            lsb = (lsb & 0x3fffffffffffffffL) | 0x8000000000000000L; // apply variant bits

            // Return the UUID
            return new UUID(msb, lsb);

        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Message digest algorithm not supported.");
        }
    }

    public static UUID getMd5Uuid(String string) {
        return getHashUuid(null, string, MESSAGE_DIGEST_MD5, VERSION_3);
    }

    public static UUID getSha1Uuid(String string) {
        return getHashUuid(null, string, MESSAGE_DIGEST_SHA1, VERSION_5);
    }

    public static UUID getMd5Uuid(UUID namespace, String string) {
        return getHashUuid(namespace, string, MESSAGE_DIGEST_MD5, VERSION_3);
    }

    public static UUID getSha1Uuid(UUID namespace, String string) {
        return getHashUuid(namespace, string, MESSAGE_DIGEST_SHA1, VERSION_5);
    }

    private static byte[] toBytes(final long number) {
        return new byte[] { (byte) (number >>> 56), (byte) (number >>> 48), (byte) (number >>> 40),
                (byte) (number >>> 32), (byte) (number >>> 24), (byte) (number >>> 16), (byte) (number >>> 8),
                (byte) (number) };
    }

    private static long toNumber(final byte[] bytes, final int start, final int length) {
        long result = 0;
        for (int i = start; i < length; i++) {
            result = (result << 8) | (bytes[i] & 0xff);
        }
        return result;
    }

    /**
     * For tests!
     */
    public static void main(String[] args) {

        String string = "JUST_A_TEST_STRING";
        UUID namespace = UUID.randomUUID(); // A custom name space

        System.out.println("Java's generator");
        System.out.println("UUID.nameUUIDFromBytes():      '" + UUID.nameUUIDFromBytes(string.getBytes()) + "'");
        System.out.println();
        System.out.println("This generator");
        System.out.println("HashUuidCreator.getMd5Uuid():  '" + HashUuidCreator.getMd5Uuid(string) + "'");
        System.out.println("HashUuidCreator.getSha1Uuid(): '" + HashUuidCreator.getSha1Uuid(string) + "'");
        System.out.println();
        System.out.println("This generator WITH name space");
        System.out.println("HashUuidCreator.getMd5Uuid():  '" + HashUuidCreator.getMd5Uuid(namespace, string) + "'");
        System.out.println("HashUuidCreator.getSha1Uuid(): '" + HashUuidCreator.getSha1Uuid(namespace, string) + "'");
    }
}

Esta es la salida:

// Java's generator
UUID.nameUUIDFromBytes():      '9e120341-627f-32be-8393-58b5d655b751'

// This generator
HashUuidCreator.getMd5Uuid():  '9e120341-627f-32be-8393-58b5d655b751'
HashUuidCreator.getSha1Uuid(): 'e4586bed-032a-5ae6-9883-331cd94c4ffa'

// This generator WITH name space
HashUuidCreator.getMd5Uuid():  '2b098683-03c9-3ed8-9426-cf5c81ab1f9f'
HashUuidCreator.getSha1Uuid(): '1ef568c7-726b-58cc-a72a-7df173463bbb'

GENERADOR ALTERNO

También puede utilizar el uuid-creator biblioteca. Vea estos ejemplos:

// Create a random-based UUID
UUID uuid = UuidCreator.getRandomBased();
// Create a name based UUID (SHA1)
String name = "JUST_A_TEST_STRING";
UUID uuid = UuidCreator.getNameBasedSha1(name);

Página del proyecto: https://github.com/f4b6a3/uuid-creador

  • Tengo algunos problemas con su respuesta: primero, ya se demostró que era incorrecto que solo puede obtener V4 de la biblioteca estándar de Java (también es posible V3). En segundo lugar, hace que parezca que no hay opciones dentro de Java además de la biblioteca estándar, junto con un ondulado manual “debido a problemas de seguridad”. Y por último, generalmente es ineficiente (programación y/o rendimiento) comenzar a depender de fuentes externas cuando hay muchas formas de hacerlo dentro de Java (a menos que lo necesite, por supuesto, por ejemplo, como parte de la creación de un registro en el servidor SQL).

    – DennisK

    6 de febrero de 2018 a las 9:25


Avatar de usuario de M. Dudek
M. Dudek

En muchos casos, necesitamos un UUID global para los objetos y, especialmente en la arquitectura basada en eventos o en el abastecimiento de eventos, tenemos que ordenar los eventos en función de la fecha, pero no necesitamos información completa sobre las marcas de tiempo.

Allí podemos usar una de las implementaciones de ULID cual es ordenable lexicográficamente.

El formato es diferente del UUID estándar, pero sigue siendo simple:

example value: 01AN4Z07BY79KA1307SR9X4MV3

 01AN4Z07BY      79KA1307SR9X4MV3

|----------|    |----------------|
 Timestamp          Randomness
   48bits             80bits

Hay implementaciones en muchos lenguajes.

Por ejemplo, en Java, hay simple liberación para eso.

Ejemplo de código:

import de.huxhorn.sulky.ulid.ULID;

ULID ulid = new ULID();

// with current timestamp
String newId = ulid.nextULID(); 

// with selected timestamp
String newId2 = ulid.nextULID(Instant
    .parse("2021-12-01T00:00:00.00Z")
    .toEpochMilli()
); 

Con Spring también puede crear un generador Bean para ULID.

@Configuration
public class UUIDGeneratorConfig {

    @Bean
    public ULID ulidGenerator() {
        return new ULID();
    }
}
@Component
public class ULIDGenerator {

    private final ULID ulid;

    public ULIDGenerator(ULID ulid) {
        this.ulid = ulid;
    }

    public String generateUUID() {
        return ulid.nextULID();
    }

    public String generateUUID(Instant timestamp) {
        return ulid.nextULID(timestamp.toEpochMilli());
    }
}

¿Ha sido útil esta solución?