如何在Java中创建类型5 UUID?

如何在Java中创建类型5 UUID?,java,uuid,Java,Uuid,在python中,要生成类型5 UUID,我们只需执行以下操作: import uuid print uuid.uuid5(uuid.NAMESPACE_URL, 'my string') 纵观历史,我不知道该怎么做。首先,没有提到类型5。他们有类型3,但签名是: nameUUIDFromBytes(byte[] name) Static factory to retrieve a type 3 (name based) UUID based on the specified byte a

在python中,要生成类型5 UUID,我们只需执行以下操作:

import uuid
print uuid.uuid5(uuid.NAMESPACE_URL, 'my string')
纵观历史,我不知道该怎么做。首先,没有提到类型5。他们有类型3,但签名是:

 nameUUIDFromBytes(byte[] name)
 Static factory to retrieve a type 3 (name based) UUID based on the specified byte array.

我们如何在Java中创建类型5 UUID?

您可以按照中提出的代码自己实现它。 然而,这确实需要一些修改,因为j.u.UUID构造函数需要很长的时间

Java8
开始,标准库似乎不支持类型5。但是像“ApacheCommonsID”这样的第三方库有确实支持它的UUID实现

编辑:这是一个功能齐全的实现:

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.UUID;

public class UUIDType5 {
    private static final Charset UTF8 = Charset.forName("UTF-8");
    public static final UUID NAMESPACE_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
    public static final UUID NAMESPACE_URL = UUID.fromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8");
    public static final UUID NAMESPACE_OID = UUID.fromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
    public static final UUID NAMESPACE_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8");

    public static UUID nameUUIDFromNamespaceAndString(UUID namespace, String name) {
        return nameUUIDFromNamespaceAndBytes(namespace, Objects.requireNonNull(name, "name == null").getBytes(UTF8));
    }

    public static UUID nameUUIDFromNamespaceAndBytes(UUID namespace, byte[] name) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException nsae) {
            throw new InternalError("SHA-1 not supported");
        }
        md.update(toBytes(Objects.requireNonNull(namespace, "namespace is null")));
        md.update(Objects.requireNonNull(name, "name is null"));
        byte[] sha1Bytes = md.digest();
        sha1Bytes[6] &= 0x0f;  /* clear version        */
        sha1Bytes[6] |= 0x50;  /* set to version 5     */
        sha1Bytes[8] &= 0x3f;  /* clear variant        */
        sha1Bytes[8] |= 0x80;  /* set to IETF variant  */
        return fromBytes(sha1Bytes);
    }

    private static UUID fromBytes(byte[] data) {
        // Based on the private UUID(bytes[]) constructor
        long msb = 0;
        long lsb = 0;
        assert data.length >= 16;
        for (int i = 0; i < 8; i++)
            msb = (msb << 8) | (data[i] & 0xff);
        for (int i = 8; i < 16; i++)
            lsb = (lsb << 8) | (data[i] & 0xff);
        return new UUID(msb, lsb);
    }

    private static byte[] toBytes(UUID uuid) {
        // inverted logic of fromBytes()
        byte[] out = new byte[16];
        long msb = uuid.getMostSignificantBits();
        long lsb = uuid.getLeastSignificantBits();
        for (int i = 0; i < 8; i++)
            out[i] = (byte) ((msb >> ((7 - i) * 8)) & 0xff);
        for (int i = 8; i < 16; i++)
            out[i] = (byte) ((lsb >> ((15 - i) * 8)) & 0xff);
        return out;
    }
}
这创建了输出:

fedb2fa3-8f5c-5189-80e6-f563dd1cb8f9

五,

根据官方python实现进行验证:

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
import java.util.UUID;

public class UUIDType5 {
    private static final Charset UTF8 = Charset.forName("UTF-8");
    public static final UUID NAMESPACE_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
    public static final UUID NAMESPACE_URL = UUID.fromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8");
    public static final UUID NAMESPACE_OID = UUID.fromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
    public static final UUID NAMESPACE_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8");

    public static UUID nameUUIDFromNamespaceAndString(UUID namespace, String name) {
        return nameUUIDFromNamespaceAndBytes(namespace, Objects.requireNonNull(name, "name == null").getBytes(UTF8));
    }

    public static UUID nameUUIDFromNamespaceAndBytes(UUID namespace, byte[] name) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException nsae) {
            throw new InternalError("SHA-1 not supported");
        }
        md.update(toBytes(Objects.requireNonNull(namespace, "namespace is null")));
        md.update(Objects.requireNonNull(name, "name is null"));
        byte[] sha1Bytes = md.digest();
        sha1Bytes[6] &= 0x0f;  /* clear version        */
        sha1Bytes[6] |= 0x50;  /* set to version 5     */
        sha1Bytes[8] &= 0x3f;  /* clear variant        */
        sha1Bytes[8] |= 0x80;  /* set to IETF variant  */
        return fromBytes(sha1Bytes);
    }

    private static UUID fromBytes(byte[] data) {
        // Based on the private UUID(bytes[]) constructor
        long msb = 0;
        long lsb = 0;
        assert data.length >= 16;
        for (int i = 0; i < 8; i++)
            msb = (msb << 8) | (data[i] & 0xff);
        for (int i = 8; i < 16; i++)
            lsb = (lsb << 8) | (data[i] & 0xff);
        return new UUID(msb, lsb);
    }

    private static byte[] toBytes(UUID uuid) {
        // inverted logic of fromBytes()
        byte[] out = new byte[16];
        long msb = uuid.getMostSignificantBits();
        long lsb = uuid.getLeastSignificantBits();
        for (int i = 0; i < 8; i++)
            out[i] = (byte) ((msb >> ((7 - i) * 8)) & 0xff);
        for (int i = 8; i < 16; i++)
            out[i] = (byte) ((lsb >> ((15 - i) * 8)) & 0xff);
        return out;
    }
}
>>>打印(uuid.uuid5(uuid.NAMESPACE_URL,'google.com'))

fedb2fa3-8f5c-5189-80e6-f563dd1cb8f9


在这种情况下,其他人需要生成版本5 UUID的库

UUID-UUID=UuidCreator.getNameBasedSha1(“google.com”);
UUID UUID=UuidCreator.getNameBasedSha1(uuidnespace.NAMESPACE_URL,“google.com”);

也许这有助于复制感谢,我会亲自查看。这就是快速检查是否有任何大型支持库支持它所得到的结果:PYou可以参考类型3 UUID的实现:-区别在于摘要是“sha1”,它首先摘要名称空间UUID的字节,然后摘要名称,而不是
md5Bytes[6]|=0x30
需要
sha1Bytes[6]|=0x50我有一个长字符串的大型数据库,这些字符串是唯一的标识符。我能够使用这个程序使用
UUIDType5.nameuidfromnamespaceandstring(UUIDType5.NAMESPACE\u URL,myStrId.getMostSignificantBits()&Long.MAX_VALUE
将它们转换为长整数,所有300万个ID仍然是唯一的。