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));
}
}
}
以下是输出:
// 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'
基于名称(v3和v5)
此实用程序类生成基于名称的UUID(MD5和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) + "'");
}
}
以下是输出:
// 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'
备用发电机
您也可以使用uuid-creator库。请参阅以下示例:
// 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);
7条答案
按热度按时间wfveoks01#
java.util.UUID.randomUUID();
oxosxuxt2#
看看与Java 5及更高版本捆绑在一起的UUID class。
例如:
wgeznvg73#
我们用一个例子来扩展马克·拜尔斯的回答:
hfyxw5xn4#
这取决于您想要什么样的UUID。
UUID
类生成版本4(随机)UUID。(UPDATE-也可以生成版本3(名称)UUID。)它还可以处理其他变体,但不能生成它们。(在本例中,“handle”表示从long
、byte[]
或String
表示构造UUID
示例,并提供一些适当的访问器。)有关UUID类型和变体的更多信息,Wikipedia中有一个很好的总结,而RFC 4122和其他规范中有一些血淋淋的细节。
pexxcrt25#
其他答案都是正确的,尤其是this one乘Stephen C。
走出Java
出于安全考虑,在Java中生成UUID值仅限于版本4(随机)。
如果您需要其他版本的UUID,一种方法是让Java应用程序访问JVM之外的内容,以通过调用以下内容生成UUID:
*命令行实用程序
几乎与所有操作系统捆绑在一起。
例如,在Mac OS X、BSD和Linux中找到的
uuidgen
。*数据库服务器
使用JDBC检索在数据库服务器上生成的UUID。
例如,
uuid-ossp
扩展经常与Postgres捆绑在一起,该扩展可以生成版本1、3和4的值,以及其他一些变体:uuid_generate_v1mc()
-生成版本1 UUID,但使用随机多播MAC地址,而不是计算机的真实的MAC地址。uuid_generate_v5(namespace uuid, name text)
-生成版本5 UUID,其工作方式与版本3 UUID类似,只是SHA-1用作散列方法。*Web服务
例如,UUID Generator创建版本1和3以及nil值和GUID。
eoigrqb66#
此答案包含2个生成器,用于基于随机数和基于名称的UUID,符合RFC-4122。请随意使用和共享。
基于随机(v4)
此实用程序类生成基于随机数的UUID:
以下是输出:
基于名称(v3和v5)
此实用程序类生成基于名称的UUID(MD5和SHA1):
以下是输出:
备用发电机
您也可以使用
uuid-creator
库。请参阅以下示例:项目页面:https://github.com/f4b6a3/uuid-creator
hmtdttj47#
在许多情况下,我们需要对象的全局UUID,特别是在事件驱动架构或事件源中,我们必须根据日期对事件进行排序,但我们不需要关于时间戳的完整信息。
这里我们可以使用ULID的一个实现,它是按字典顺序排序的。
该格式与标准UUID不同,但仍然很简单:
有许多语言的实现。
例如,在Java中,有一个简单的lib。
代码示例:
使用Spring,您还可以为ULID生成器创建Bean。
一个二个一个一个