chris dutrow
¿Cuáles son algunas de las mejores formas de crear un GUID/UUID en Java?
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
marca byers
Echa un vistazo a la clase UUID incluido con Java 5 y versiones posteriores.
Por ejemplo:
- Si desea un UUID aleatorio, puede usar el UUID aleatorio método.
- Si desea que un UUID se inicialice con un valor específico, puede usar el constructor de UUID o el de la cadena método.
-
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
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
esteban c
Depende de que tipo de UUID quieres.
-
El Java estándar
UUID
la clase genera Versión 4 (aleatorios) UUID. (ACTUALIZAR – Versión 3 (nombre) También se pueden generar UUID). También puede manejar otras variantes, aunque no puede generarlas. (En este caso, “manejar” significa construirUUID
instancias delong
,byte[]
oString
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.
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, eluuid-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
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());
}
}
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