1. 概述

在我们的应用程序中,我们经常需要为各种目的生成唯一的标识符。一个常用的生成唯一标识符的方法是通用唯一标识符(UUID)。

在这个教程中,我们将探讨如何在Java中从字符串生成相同的UUID。

2. 问题介绍

当我们谈论从字符串生成UUID时,可能会有以下两种情况:

  • 情景1 - 输入字符串是标准的UUID字符串格式。
  • 情景2 - 给定的字符串是自由形式的。

接下来,我们将更深入地了解如何从字符串生成UUID对象。当然,我们会涵盖这两种情况。

为了简化,我们将使用单元测试断言来验证每种方法是否能产生预期的结果。

3. 输入字符串是标准UUID表示

标准的UUID字符串格式由五个由破折号分隔的十六进制数字组组成,例如:

String inputStr = "bbcc4621-d88f-4a94-ae2f-b38072bf5087";

在这种情况下,我们希望从给定的字符串获取一个UUID对象。此外,生成的UUID对象的字符串表示必须等于输入字符串。换句话说,这意味着generatedUUID.toString()应与输入字符串相同。

因此,确切地说,我们想要解析输入字符串的标准UUID格式,并根据解析值构建一个新的UUID对象。

为此,我们可以使用UUID.fromString()方法。接下来,让我们编写一个测试来看看它的工作原理:

String inputStr = "bbcc4621-d88f-4a94-ae2f-b38072bf5087";

UUID uuid = UUID.fromString(inputStr);
UUID uuid2 = UUID.fromString(inputStr);
UUID uuid3 = UUID.fromString(inputStr);

assertEquals(inputStr, uuid.toString());

assertEquals(uuid, uuid2);
assertEquals(uuid, uuid3);

如上所示的测试所示,我们简单地调用UUID.fromString(inputStr)来生成UUID对象。标准的UUID类负责处理输入解析和UUID生成。

在我们的测试中,我们从同一个输入字符串生成了多个UUID对象,结果发现所有由输入字符串生成的UUID对象都相等。

使用UUID.fromString()方法很方便。但是,值得一提的是,输入字符串必须符合标准的UUID格式,否则方法将抛出IllegalArgumentException

String inputStr = "I am not a standard UUID representation.";
assertThrows(IllegalArgumentException.class, () -> UUID.fromString(inputStr));

4. 输入是自由形式的字符串

我们已经看到UUID.fromString()可以方便地从标准UUID格式字符串构建UUID对象。现在来看看如何从自由形式的字符串生成UUID对象。

UUID类提供了nameUUIDFromBytes(byte[] name)方法来构建版本3(也称为基于名称的)的UUID对象。

由于该方法只接受字节数组(byte[]),我们需要将输入字符串转换为字节数组才能使用UUID.nameUUIDFromBytes()

String inputStr = "I am not a standard UUID representation.";

UUID uuid = UUID.nameUUIDFromBytes(inputStr.getBytes());
UUID uuid2 = UUID.nameUUIDFromBytes(inputStr.getBytes());
UUID uuid3 = UUID.nameUUIDFromBytes(inputStr.getBytes());

assertTrue(uuid != null);

assertEquals(uuid, uuid2);
assertEquals(uuid, uuid3);

如上所示的测试中,我们通过三次调用UUID.nameUUIDFromBytes()并使用相同的输入字符串生成了三个UUID对象,这三者彼此相等。

内部而言,这个方法根据输入字节数组的MD5散列返回一个UUID对象。因此,对于给定的输入名称,生成的UUID是保证唯一的。

此外,值得一提的是,通过UUID.nameUUIDFromBytes()方法生成的UUID对象是版本3的UUID。我们可以使用version()方法进行验证:

UUID uuid = UUID.nameUUIDFromBytes(inputStr.getBytes());
...
assertEquals(3, uuid.version());

版本5 UUID使用SHA-1(160位)哈希函数而不是MD5。 如果需要版本5的UUID,可以直接使用我们在介绍版本3和5 UUID时创建的generateType5UUID(String name)方法:

String inputStr = "I am not a standard UUID representation.";

UUID uuid = UUIDGenerator.generateType5UUID(inputStr);
UUID uuid2 = UUIDGenerator.generateType5UUID(inputStr);
UUID uuid3 = UUIDGenerator.generateType5UUID(inputStr);

assertEquals(5, uuid.version());

assertTrue(uuid != null);

assertEquals(uuid, uuid2);
assertEquals(uuid, uuid3);

5. 总结

在这篇文章中,我们探讨了如何从字符串生成相同的UUID对象。我们根据输入格式划分了两种情况:

  • 标准UUID格式字符串 - 使用UUID.fromString()
  • 自由形式字符串 - 使用UUID.nameUUIDFromBytes()

如往常一样,这里展示的所有代码片段都可以在GitHub上找到。