web-dev-qa-db-ja.com

UUIDは異なる文字列から同じです

私は2つの異なる文字列を持っていますが、UUIDに解析した後は同じように見えます

public static void main(String[] args) {
    try {
        UUID t1 = UUID.fromString("38e1036d-7527-42a3-98ca-f2f19d3155db");
        UUID t2 = UUID.fromString("123438e1036d-7527-42a3-98ca-f2f19d3155db");
        System.out.println(t1.toString().equals(t2.toString()));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

なぜそうなのでしょうか?

46
Jerry06

「123438e1036d-7527-42a3-98ca-f2f19d3155db」

これはUUIDではありません。これは、「1234」とUUIDを連結した文字列です。ここでの問題は、パーサーが例外をスローすることでこれを通知する必要があることです。代わりに、UUIDを実際にどこかに埋めるように最善を尽くします。

連結された文字列からUUIDを抽出すると、最初のUUIDと同じになります。これは、観察している正しい結果です。

パーサーを分析できます(リンクを提供してくれた@ tim-biegeleisenに感謝します):

public static UUID fromString(String name) {
    String[] components = name.split("-");
    if (components.length != 5)
        throw new IllegalArgumentException("Invalid UUID string: "+name);
    for (int i=0; i<5; i++)
        components[i] = "0x"+components[i];

    long mostSigBits = Long.decode(components[0]).longValue();
    mostSigBits <<= 16;
    mostSigBits |= Long.decode(components[1]).longValue();
    mostSigBits <<= 16;
    mostSigBits |= Long.decode(components[2]).longValue();

    long leastSigBits = Long.decode(components[3]).longValue();
    leastSigBits <<= 48;
    leastSigBits |= Long.decode(components[4]).longValue();

    return new UUID(mostSigBits, leastSigBits);
}

ご覧のとおり、ハイフンで制限されたグループの数をカウントすること以外には検証はありません。それらのグループを取得し、それらを位置にシフトします。最初のグループの前に余分な文字を追加しました。これが最も重要な部分です。最初に解析されて保存され、次に最も重要な部分を占めるまで上にシフトされます。現在、想定よりも左にあるすべてのビットがlong制限から押し出されるため、それらは完全に無視されます。

68
Agent_L

[〜#〜] uuid [〜#〜] は、データの 128ビット を格納します。それ以上与えると、保存できません。私はそれがあなたにエラーを与えないことに驚いていますが、それがそうでなければより高いビットを切り捨てることに驚かないです。

int i = 0x38e1036d;
int j = (int) 0x123438e1036dL;
i == j;
53
Peter Lawrey

2番目のコンポーネント「7527」のビットシフトにより、最初のコンポーネント「123438e1036d」に加えた変更の影響が除去され、同じUUIDが生成されます。

最初のコンポーネントの処理自体は異なりますが、uuidの2番目のコンポーネントがシフトされると、この効果は失われます。

9
UserF40

これは、右から左にチェックし、UUIDとして32文字のみを使用し、その他を削除するためです。順番に32文字が取得されると、Serializableインターフェイスを実装するため、他の文字は考慮されません。

public final class UUID
  extends Object
  implements Serializable, Comparable<UUID>

1234は、2番目のUUIDから削除されます。

コードは次のとおりです。

 public static UUID More ...fromString(String name) {
    String[] components = name.split("-");
    if (components.length != 5)
        throw new IllegalArgumentException("Invalid UUID string: "+name);
    for (int i=0; i<5; i++)
        components[i] = "0x"+components[i];

    long mostSigBits = Long.decode(components[0]).longValue();
    mostSigBits <<= 16;
    mostSigBits |= Long.decode(components[1]).longValue();
    mostSigBits <<= 16;
    mostSigBits |= Long.decode(components[2]).longValue();

    long leastSigBits = Long.decode(components[3]).longValue();
    leastSigBits <<= 48;
    leastSigBits |= Long.decode(components[4]).longValue();

    return new UUID(mostSigBits, leastSigBits);
    }
4
Zubair Nabi

これは、Java 8、2016年6月に報告されたバグの既知のバグです。 http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=8159339

http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=8165199 (2016年8月に報告):

4d4d8f3b-3b81-44f3-968d-d1c1a48b4ac8は有効なUUIDです。

4d4d8f-3b3b81-44f3-968d-d1c1a48b4ac8はありません(最初のダッシュを2文字左に移動しました)

無効なUUID :: fromString()を呼び出すと、004d4dbf-3b81-44f3-968d-d1c1a48b4ac8を表すUUIDが生成されます。

4
Fuad Efendi