大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
转自:http://www.itwanger.com/java/2020/08/02/java-uuid.html
UUID,全名叫做 Universally Unique Identifier,也就是通用唯一标识符的意思。有时候,也叫做全局唯一标识符,英文全名叫做 Globally Unique Identifier,简拼为 GUID。
来看一下 UUID 的格式:
123e4567-e89b-12d3-a456-556642440000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
由四个中划线“-”隔开,第一部分的长度为 8,第二部分、第三部分和第四部分的长度都为 4,第四部分的长度为 12,总长度为 36,是固定的。除中划线外的每个字符都代表一个十六进制的数字,并不是随机的任意字母+数字的字符串。
M 表示 UUID 的版本,N 为 UUID 的变体(Variants)。
M 的值有 5 个可选项:
版本 1:UUID 是根据时间和 MAC 地址生成的;
版本 2:UUID 是根据标识符(通常是组或用户 ID)、时间和节点 ID生成的;
版本 3:UUID 是通过散列(MD5 作为散列算法)、名字空间(namespace)、标识符和名称生成的;
版本 4 – UUID 使用随机性或伪随机性生成;
版本 5 类似于版本 3(SHA1 作为散列算法)。
为了能兼容过去的 UUID,以及应对未来的变化,因此有了变体(Variants)这一概念。
目前已知的变体有下面 4 种:
变体 0:规定变体0的二进制格式为 0xxx,为了向后兼容预留。
变体 1:规定变体1的二进制格式为 10xx,当前正在使用的。
变体 2:规定变体2的二进制格式为 11xx,为早期微软的 GUID 预留。
变体 3:规定变体3的二进制格式为 111x,为将来的扩展预留,目前暂未使用。
在上例中,M 是 1,N 是 a(二进制为 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,a 的二进制为 1010,b 的二进制为 1011,都符合 10xx 的格式。
由于 UUID 是全局唯一的,重复 UUID 的概率接近零,可以忽略不计。所以 Java 的 UUID 通常可用于以下地方:
-
随机生成的文件名;
-
Java Web 应用程序的 sessionID;
-
数据库表的主键;
-
事务 ID(UUID 生成算法非常高效,每台计算机每秒高达 1000 万次)。
在 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 对象的话,就需要传递两个参数,long 型的最高位 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() 方法生成了一个版本 4 的 UUID,这也是生成 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() 会生成一个版本 3 的 UUID,不过需要传递一个名称的字节数组作为参数。
示例如下:
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
除了使用 JDK 原生的 API 之外,还可以使用 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() 可用于生成版本 1 的 UUID,Generators.randomBasedGenerator().generate() 可用于生成版本 4 的 UUID。
来看一下输出结果:
UUID : ebee82f5-cfd2-11ea-82a7-8536e13d4951
UUID 版本 : 1
UUID : d2ccc752-c824-4bbc-8cc7-52c8246bbc6a
UUID 版本 : 4
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190695.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...