我想知道是否有一种方法可以基于 String.生成相同的 UUID 我尝试用 UUID,它看起来不提供这个功能。
String.
您可以通过这种方式使用 UUID 为您的输入 String 获得总是相同的 UUID:
String aString="JUST_A_TEST_STRING"; String result = UUID.nameUUIDFromBytes(aString.getBytes()).toString();
UUID.nameUUIDFromBytes()只生成 MD5 UUID,但是 SHA1优于 MD5,如果向下兼容不是问题的话。
UUID.nameUUIDFromBytes()
下面的实用程序类生成 MD5 UUID 和 SHA-1 UUID。
package com.example; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.UUID; /** * Generates UUIDv3 (MD5) and UUIDv5 (SHA1). * * It is fully compliant with RFC-4122. */ public class HashUuid { private static final int V3 = 3; // MD5 private static final int V5 = 5; // SHA-1 private static final String HASH_V3 = "MD5"; private static final String HASH_V5 = "SHA-1"; public static final UUID NAMESPACE_DNS = new UUID(0x6ba7b8109dad11d1L, 0x80b400c04fd430c8L); public static final UUID NAMESPACE_URL = new UUID(0x6ba7b8119dad11d1L, 0x80b400c04fd430c8L); public static final UUID NAMESPACE_OID = new UUID(0x6ba7b8129dad11d1L, 0x80b400c04fd430c8L); public static final UUID NAMESPACE_X500 = new UUID(0x6ba7b8149dad11d1L, 0x80b400c04fd430c8L); public static UUID v3(String name) { return generate(V3, HASH_V3, null, name); } public static UUID v5(String name) { return generate(V5, HASH_V5, null, name); } public static UUID v3(UUID namespace, String name) { return generate(V3, HASH_V3, namespace, name); } public static UUID v5(UUID namespace, String name) { return generate(V5, HASH_V5, namespace, name); } private static UUID generate(int version, String algorithm, UUID namespace, String name) { MessageDigest hasher = hasher(algorithm); if (namespace != null) { ByteBuffer ns = ByteBuffer.allocate(16); ns.putLong(namespace.getMostSignificantBits()); ns.putLong(namespace.getLeastSignificantBits()); hasher.update(ns.array()); } hasher.update(name.getBytes(StandardCharsets.UTF_8)); ByteBuffer hash = ByteBuffer.wrap(hasher.digest()); final long msb = (hash.getLong() & 0xffffffffffff0fffL) | (version & 0x0f) << 12; final long lsb = (hash.getLong() & 0x3fffffffffffffffL) | 0x8000000000000000L; return new UUID(msb, lsb); } private static MessageDigest hasher(String algorithm) { try { return MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(String.format("%s not supported.", algorithm)); } } /** * For tests! */ public static void main(String[] args) { UUID namespace = UUID.randomUUID(); String name = "JUST_A_TEST_STRING"; System.out.println(String.format("UUID.nameUUIDFromBytes(): '%s'", UUID.nameUUIDFromBytes(name.getBytes()))); System.out.println(); System.out.println(String.format("HashUuid.v3(name): '%s'", HashUuid.v3(name))); System.out.println(String.format("HashUuid.v5(name): '%s'", HashUuid.v5(name))); System.out.println(String.format("HashUuid.v3(namespace, name): '%s'", HashUuid.v3(namespace, name))); System.out.println(String.format("HashUuid.v5(namespace, name): '%s'", HashUuid.v5(namespace, name))); } }
This is the output:
UUID.nameUUIDFromBytes(): '9e120341-627f-32be-8393-58b5d655b751' HashUuid.v3(name): '9e120341-627f-32be-8393-58b5d655b751' HashUuid.v5(name): 'e4586bed-032a-5ae6-9883-331cd94c4ffa' HashUuid.v3(namespace, name): 'f0043437-723b-308f-a6c0-74ec36ddf9c2' HashUuid.v5(namespace, name): '18a45fd8-8fab-5647-aad7-1d3264932180'
另外,你也可以使用 uuid-creator:
uuid-creator
// Create a UUIDv5 (SHA1) String name = "JUST_A_TEST_STRING"; UUID uuid = UuidCreator.getNameBasedSha1(name);
如果您正在寻找 Javascript 的替代方案,请参考 uuid-by-string,它也提供了使用 SHA-1或 MD5散列函数的选项。
你应该使用 UUID v5.
版本3和版本5的 UUID 是通过散列名称空间标识符和名称生成的。版本3使用 MD5作为哈希算法,版本5使用 SHA-1。1-维基百科
UUID v5需要 namespace。这个名称空间应该是 UUID v4,您可以只使用 在线生成。命名空间确保对于给定的输入,输出总是相同的。
可以找到 UUID v5的一个可能的实现 给你:
<!-- https://search.maven.org/artifact/com.github.f4b6a3/uuid-creator --> <dependency> <groupId>com.github.f4b6a3</groupId> <artifactId>uuid-creator</artifactId> <version>3.6.0</version> </dependency>
它可用于以下方面:
UUID namespace = ; // todo generate a UUID v4. String input = "input"; UUID uuid = UuidCreator.getNameBasedSha1(namespace, input);
(在某种程度上,名称空间的作用类似于随机数生成器的种子。相比之下,虽然种子应该是随机的,但我们的名称空间是常量。这就迫使我们的生成器总是为给定的输入产生相同的值。)