Java Сравнение UUIDНе работает правильно для UUID типа 1 - PullRequest
5 голосов
/ 04 февраля 2020

Во время работы над сценарием использования, когда данные должны быть отсортированы по UUID, которые все являются Типом 1 или основаны на времени и сгенерированы с использованием библиотеки драйверов Datastax Cassandra Java (UUIDS.timebased ()), я обнаружил, что UUID.compareTo неправильно сортирует некоторые из UUID. Логическое значение c в CompareTo равно

    /**
 * Compares this UUID with the specified UUID.
 *
 * <p> The first of two UUIDs is greater than the second if the most
 * significant field in which the UUIDs differ is greater for the first
 * UUID.
 *
 * @param  val
 *         {@code UUID} to which this {@code UUID} is to be compared
 *
 * @return  -1, 0 or 1 as this {@code UUID} is less than, equal to, or
 *          greater than {@code val}
 *
 */
public int compareTo(UUID val) {
    // The ordering is intentionally set up so that the UUIDs
    // can simply be numerically compared as two numbers
    return (this.mostSigBits < val.mostSigBits ? -1 :
            (this.mostSigBits > val.mostSigBits ? 1 :
             (this.leastSigBits < val.leastSigBits ? -1 :
              (this.leastSigBits > val.leastSigBits ? 1 :
               0))));
}

У меня было 2 идентификатора UUID, сгенерированных с использованием драйвера dasastax cassandra для java.

UUID uuid1 = java.util.UUID.fromString("7fff5ab0-43be-11ea-8fba-0f6f28968a17")
UUID uuid2 = java.util.UUID.fromString("80004510-43be-11ea-8fba-0f6f28968a17")
uuid1.timestamp() //137997224058510000
uuid2.timestamp() //137997224058570000

Из вышесказанного очевидно, что что uuid1 меньше, чем uuid2, но когда мы сравниваем их, используя метод UUID compareTo, мы получаем другой результат. Мы должны получить выходные данные как -1, поскольку это должно быть меньше, но мы получаем ответ как 1, который показывает, что этот uuid1 больше, чем uuid2

uuid1.compareTo(uuid2) //output - 1

. При дальнейшем анализе этого обнаружил, что msb для uuid2 преобразуется в отрицательное число, где в качестве msb для uuid1 положительное число. Из-за этого logi c в compareTo возвращает значение 1 вместо -1.

u_7fff5ab0 = {UUID@2623} "7fff5ab0-43be-11ea-8fba-0f6f28968a17"
mostSigBits = 9223190274975338986
leastSigBits = -8090136810520933865

u_80004510 = {UUID@2622} "80004510-43be-11ea-8fba-0f6f28968a17"
mostSigBits = -9223296100696452630
leastSigBits = -8090136810520933865

Нормально ли это поведение с UUID и их сравнение друг с другом? Если да, то как мы будем обрабатывать сортировку таких UUID на основе времени?

Спасибо

1 Ответ

2 голосов
/ 04 февраля 2020

Обратите внимание, что сравнение UUID на основе времени требует особого внимания, Из документов :

И наконец, обратите внимание, что сортировка timeuuid Кассандры не совместима с UUID.compareTo (java .util.UUID) и, следовательно, UUID, созданный этим методом, не обязательно является нижней границей для этого последнего метода.

UUID, основанные на времени, не следует сравнивать с java.util.UUID#compareTo. Чтобы сравнить UUID, основанный на двух временах, вы должны сравнить время ; в этих двух UUID содержится . вам нужна реализация пользовательского метода Utility или просто сравните две метки времени. Вот пример, как это сделать:

// must be timebased UUID
int compareTo(UUID a, UUID b){
   return Long.compare(UUIDs.unixTimestamp(a),UUIDs.unixTimestamp(b));
}

Чтобы узнать больше, go через это DOCS .

...