2016-10-25 12 views
4

、我々は単に行うことができますタイプ5 UUID作るために:JavaでType 5 UUIDを作成するには? Pythonでは

java documentation for java.util.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を作ることができますか?

+0

は多分これは[のhttps://modules.ceylon-lang.org/repo/1/herd/uuid/0.0.10/module-doc/api/index.html –

+0

が重複する可能性を支援しますこのJava UUID5実装でユニットテストをパスしない](h ttp://stackoverflow.com/questions/16501357/this-java-uuid5-implementation-not-passing-unit-test) – MordechayS

答えて

6

https://stackoverflow.com/a/28776880/1452094で提案されているコードに従って、自分で実装することができます。 しかし、これは、j.u.UUIDコンストラクタがlongを取るので、少しの手間が必要です。

Java 8現在、標準ライブラリはタイプ5をサポートしていないようですが、 "Apache Commons Id"のようなサードパーティライブラリでは、それをサポートする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; 
    } 
} 

それは、私は次のコードを実行した動作することを確認するには:

public static void main(String[] args) { 
    UUID test = UUIDType5.nameUUIDFromNamespaceAndString(NAMESPACE_URL, "google.com"); 
    System.out.println(test); 
    System.out.println(test.version()); 
} 

これは、出力を作成しました:

fedb2fa3- 8f5c-5189-80e6-f563dd1cb8f9

>>>プリント(uuid.uuid5(uuid.NAMESPACE_URL、 'google.com'))

fedb2fa3-8f5c-5189:公式Python実装に対して検証5

-80e6-f563dd1cb8f9

+2

ありがとう私は自分のローリングをチェックアウトします。 [Apache Commons Idは公式リリースをまだ持っていないようです。](http://commons.apache.org/sandbox/commons-id/downloads.html) –

+0

私はすぐに大サポートされているライブラリをサポートしています:P – Kiskae

+0

タイプ3のUUIDの実装を参照できます:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util /UUID.java#UUID.nameUUIDFromBytes%28byte%5B%5D%29 - ダイジェストが "sha1"である場合、名前空間UUIDのバイトを最初にダイジェストし、次に名前空間名と 'md5Bytes [6] | = 0x30; 'sha1Bytes [6] | = 0x50;'にする必要があります。 – Kiskae

関連する問題