Why are two different java.util.UUID objects comparing as equal?

Arun Prabhath :

I have created two instances of java.util.UUID as given below. One is created from UUID.randomUUID() and the other is the same but with some additional digits prepended to the beginning. When these are compared using the UUID.equals method it returns true:

UUID uuid1 = UUID.randomUUID();
UUID uuid2 = UUID.fromString("12345"+uuid1.toString());
System.out.println(uuid1.equals(uuid2));  // this gives true.

I think the added digits are being discarded and both give the same UUID string value. Why this is happening?

Nyamiou The Galeanthrope :

In the UUID.fromString(...) method you have this:

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);
}

The first thing it does it to separate the parts of the UUID into components, then it will create two longs. Here you changed only the first component of the UUID by adding leading characters, your UUID string is for example "12345894ff97a-039b-47fe-8a72-950b7766d50c". So the first component is "12345894ff97a", when it will do

long mostSigBits = Long.decode(components[0]).longValue();

Then you will have "320256540146042" which actual HEX representation is "12345894ff97a", then you have a bit operation that will shift the long 16 bits to the left:

mostSigBits <<= 16;

This will result in "2541588541301456896" which actual HEX representation is "2345894ff97a0000" (we moved 16 bits so 4 hex chars) and you start to see what is happening, see the long format is only 64 bits, so when shifting the bits some are lost, here the first character "1" is lost. After that in the freed space it will add the second component:

mostSigBits |= Long.decode(components[1]).longValue();

This will result in "2541588541301457819" which actual HEX representation is "2345894ff97a039b", then it will shift the long 16 bits to the left again:

mostSigBits <<= 16;

This will result in "-8552342864911466496" which actual HEX representation is "894ff97a039b0000" and here your leading characters are all lost because of the long 64 bits size.

I don't need to explain the rest of the method (at the end mostSigBits is "894ff97a039b47fe" and leastSigBits is "8a72950b7766d50c"), you can already understand that any leading character added to an UUID will be lost when calling UUID.fromString(..) since only the last 8 hex characters (32 bits) are going to be considered, the rest is going to be lost.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=440735&siteId=1