Забавно, вы не знаете, как Java генерирует UUID

Java
Забавно, вы не знаете, как Java генерирует UUID

Сначала посмотрите, а потом лайкните, дайте себе время подумать, поиск в WeChat [Тихий король 2】Подпишитесь на этого талантливого программиста.
эта статьяGitHub github.com/itwangerОн был включен, а также есть вопросы для интервью, организованные ведущими производителями, а также моя серия статей.

Непослушный читатель пошутил в сообщении из серии статей «Я иду», которую я написал ранее: «Второй брат, ты родился из ничего, Сяо Ван?» Нет, нет, это не так. Он сражался вместе со мной, работая не покладая рук и заставляя меня любить и ненавидеть. Я люблю его за то, что он добросовестный и трудолюбивый, и у него хорошие отношения со мной; я ненавижу его за то, что время от времени он останавливается на секунду и задает мне какие-то нелепые вопросы, например, на этот раз: «Второй брат, ты можешь сказать мне о Java? Как сгенерировать UUID?"

UUID, полное название Universally Unique Identifier, что означает универсальный уникальный идентификатор. Иногда его также называют глобальным уникальным идентификатором.Полное английское имя называется глобальным уникальным идентификатором, который для краткости записывается как GUID.

Взгляните на формат UUID:

123e4567-e89b-12d3-a456-556642440000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

Разделенные четырьмя черточками «-», длина первой части равна 8, длина второй и третьей частей равна 4, длина четвертой части равна 12, а общая длина составляет 36, что является фиксированным. Каждая часть представляет собой шестнадцатеричное число, обратите внимание, что это не случайная последовательность букв и цифр.

M представляет версию UUID, а N — варианты UUID.

Значение M имеет 5 вариантов:

  • Версия 1: UUID генерируется из времени и MAC-адреса;

  • Версия 2: UUID генерируется из идентификатора (обычно идентификатора группы или пользователя), времени и идентификатора узла;

  • Версия 3: UUID генерируется путем хэширования (MD5 в качестве алгоритма хеширования) идентификатора и имени пространства имен;

  • Версия 4 — UUID генерируются с использованием случайности или псевдослучайности;

  • Версия 5 аналогична версии 3 (SHA1 в качестве алгоритма хеширования).

Чтобы быть совместимым с прошлыми UUID и иметь дело с будущими изменениями, создается концепция вариантов.

В настоящее время известно 4 варианта:

  • Вариант 0: формат 0xxx, зарезервированный для обратной совместимости.

  • Вариант 1: Формат 10xx, используемый в настоящее время.

  • Вариант 2: формат 11xx, зарезервированный для ранних идентификаторов GUID Microsoft.

  • Вариант 3: Формат 111x зарезервирован для будущего расширения, в настоящее время не используется.

В приведенном выше примере M равно 1, а N равно (1010 в двоичном формате, соответствующему формату 10xx), что означает, что этот UUID является «версией 1», «вариантом 1» UUID.

Большинство используемых в настоящее время UUID в основном относятся к варианту 1, а значение N равно одному из 8, 9, a и b.

System.out.println(Integer.toBinaryString(Integer.valueOf("8",16))); // 1000
System.out.println(Integer.toBinaryString(Integer.valueOf("a",16))); // 1010
System.out.println(Integer.toBinaryString(Integer.valueOf("9",16))); // 1001
System.out.println(Integer.toBinaryString(Integer.valueOf("b",16))); // 1011

8 в двоичном формате1000, двоичное число 9 равно1001, двоичный файл a1010, двоичный код b равен1011, все встречаются10xxформат.

Поскольку UUID глобально уникальны, вероятность повторения UUID близка к нулю и может быть проигнорирована. Таким образом, UUID Java обычно используется в следующих местах:

  • случайно сгенерированное имя файла;

  • sessionID веб-приложения Java;

  • Первичный ключ таблицы базы данных;

  • Идентификатор транзакции (алгоритм генерации UUID очень эффективен, до 10 миллионов раз в секунду на компьютер).

В Java есть класс с именем UUID, вjava.utilпод пакет.

package java.util;
public final class UUID implements java.io.Serializable, Comparable<UUID> {
}

Этот класс имеет только один конструктор:

public UUID(long mostSigBits, long leastSigBits) {
    this.mostSigBits = mostSigBits;
    this.leastSigBits = leastSigBits;
}

Чтобы использовать конструктор для создания объекта UUID, вам необходимо передать два параметра: самый высокий UUID длинного типа и самый низкий UUID.

long msb = System.currentTimeMillis();
long lsb = System.currentTimeMillis();
UUID uuidConstructor = new UUID(msb, lsb);
System.out.println("UUID : "+uuidConstructor);

Результат выглядит следующим образом:

UUID : 00000173-8efd-1b7c-0000-01738efd1b7c

Класс UUID предоставляет статический методrandomUUID():

public static UUID randomUUID() {
    SecureRandom ng = UUID.Holder.numberGenerator;

    byte[] randomBytes = new byte[16];
    ng.nextBytes(randomBytes);
    randomBytes[6]  &= 0x0f;  /* clear version        */
    randomBytes[6]  |= 0x40;  /* set to version 4     */
    randomBytes[8]  &= 0x3f;  /* clear variant        */
    randomBytes[8]  |= 0x80;  /* set to IETF variant  */
    return new UUID(randomBytes);
}

randomUUID()Метод генерирует UUID версии 4, что также является наиболее удобным способом создания UUID. Если вы используете только родной JDK, это в основном то же самое.

Пример выглядит следующим образом:

UUID uuid4 = UUID.randomUUID();
int version4 = uuid4.version();
System.out.println("UUID:"+ uuid4+" 版本 " + version4);

Вывод программы следующий:

UUID:8c943921-d83e-424a-a627-a12d3cb474db 版本 4

Кроме того, класс UUID также предоставляет два других статических метода, один из которыхnameUUIDFromBytes():

public static UUID nameUUIDFromBytes(byte[] name) {
    MessageDigest md;
    try {
        md = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException nsae) {
        throw new InternalError("MD5 not supported", nsae);
    }
    byte[] md5Bytes = md.digest(name);
    md5Bytes[6]  &= 0x0f;  /* clear version        */
    md5Bytes[6]  |= 0x30;  /* set to version 3     */
    md5Bytes[8]  &= 0x3f;  /* clear variant        */
    md5Bytes[8]  |= 0x80;  /* set to IETF variant  */
    return new UUID(md5Bytes);
}

nameUUIDFromBytes()Генерируется UUID версии 3, но в качестве параметра передается байтовый массив имен.

Пример выглядит следующим образом:

UUID uuid3 = UUID.nameUUIDFromBytes("test".getBytes());
int version3 = uuid3.version();
System.out.println("UUID:"+ uuid3+" 版本 " + version3);

Вывод программы следующий:

UUID:098f6bcd-4621-3373-8ade-4e832627b4f6 版本 3

ВторойfromString():

public static UUID fromString(String name) {
    int len = name.length();
    if (len > 36) {
        throw new IllegalArgumentException("UUID string too large");
    }

    int dash1 = name.indexOf('-', 0);
    int dash2 = name.indexOf('-', dash1 + 1);
    int dash3 = name.indexOf('-', dash2 + 1);
    int dash4 = name.indexOf('-', dash3 + 1);
    int dash5 = name.indexOf('-', dash4 + 1);

    // For any valid input, dash1 through dash4 will be positive and dash5
    // negative, but it's enough to check dash4 and dash5:
    // - if dash1 is -1, dash4 will be -1
    // - if dash1 is positive but dash2 is -1, dash4 will be -1
    // - if dash1 and dash2 is positive, dash3 will be -1, dash4 will be
    //   positive, but so will dash5
    if (dash4 < 0 || dash5 >= 0) {
        throw new IllegalArgumentException("Invalid UUID string: " + name);
    }

    long mostSigBits = Long.parseLong(name, 0, dash1, 16) & 0xffffffffL;
    mostSigBits <<= 16;
    mostSigBits |= Long.parseLong(name, dash1 + 1, dash2, 16) & 0xffffL;
    mostSigBits <<= 16;
    mostSigBits |= Long.parseLong(name, dash2 + 1, dash3, 16) & 0xffffL;
    long leastSigBits = Long.parseLong(name, dash3 + 1, dash4, 16) & 0xffffL;
    leastSigBits <<= 48;
    leastSigBits |= Long.parseLong(name, dash4 + 1, len, 16) & 0xffffffffffffL;

    return new UUID(mostSigBits, leastSigBits);
}

fromString()Метод создаст объект UUID на основе указанной строки UUID.Если указанная строка UUID не соответствует формату UUID, будет выдано исключение IllegalArgumentException.

Пример выглядит следующим образом:

UUID uuid = UUID.fromString("38400000-8cf0-11bd-b23e-10b96e4ef00d");
int version = uuid.version();
System.out.println("UUID:"+ uuid+" 版本 " + version);

Вывод программы следующий:

UUID:38400000-8cf0-11bd-b23e-10b96e4ef00d 版本 1

Кроме собственного API JDK, вы также можете использоватьcom.fasterxml.uuid.Generators, вам нужно сначала добавить в проект зависимость Maven этого класса.

<dependency>
    <groupId>com.fasterxml.uuid</groupId>
    <artifactId>java-uuid-generator</artifactId>
    <version>3.1.4</version>
</dependency>

Затем мы рассмотрим, как его использовать:

/**
 * @author 沉默王二,一枚有趣的程序员
 */
public class UUIDVersionExample {
    public static void main(String[] args) {
        UUID uuid1 = Generators.timeBasedGenerator().generate();
        System.out.println("UUID : "+uuid1);
        System.out.println("UUID 版本 : "+uuid1.version());

        UUID uuid2 = Generators.randomBasedGenerator().generate();
        System.out.println("UUID : "+uuid2);
        System.out.println("UUID 版本 : "+uuid2.version());
    }
}

Generators.timeBasedGenerator().generate()Может использоваться для генерации UUID версии 1,Generators.randomBasedGenerator().generate()Может использоваться для создания UUID версии 4.

Взгляните на вывод:

UUID : ebee82f5-cfd2-11ea-82a7-8536e13d4951
UUID 版本 : 1
UUID : d2ccc752-c824-4bbc-8cc7-52c8246bbc6a
UUID 版本 : 4

Ну, я думаю, я объяснил все об УУИД. Спешите и отправьте эту статью в Сяо Ван для предварительного просмотра, чтобы он мог получить понимание.


Я Тихий Король Эр, программист с красивой внешностью, но полагающийся на талант.Подпишитесь, чтобы повысить эффективность обучения, не забудьте три последовательных ах, лайкните, любимый, оставьте сообщение, я не выбираю, Олли дает его.

Примечание. Если в статье есть какие-либо проблемы, пожалуйста, исправьте их.

Если вы считаете, что статья полезна для вас, добро пожаловать в поиск WeChat »Тихий король 2"Прочитал в первый раз, ответь"нуб«Кроме того, руководство по Java Xiaobai версии 2.0, содержащее более 40 000 слов, эта статьяGitHub github.com/itwangerОн был записан, добро пожаловать в звезду.