随机数一般也是会被常使用到的,比如在造一些模拟测试数据的场景,或者说是非高端应用的场景会被使用。而全局唯一ID的使用则相反,应用场景更广,更专业,更科学,比如在批量保存数据时,需要提前生成ID等(请注意随机数与UUID两者是不同的东西)。本次就分享一下个人这些年所涉及到的一些实现方式,基本上是罗列呈现一下,至于实现原理和更科学的应用就需要读者自行深入了,所以,参考如下。
随机数
Java里面提供的随机数产生方式列举了其中的4种,大多数也可以随机出Integer、Long、Float、Double、Boolean,或指定范围内大小的随机数,参考代码如下。
@Test
public void math() {
System.out.println("随机数 0 - 1 之间:" + Math.random());
System.out.println("随机数 0 - 1000 之间:" + (int) (Math.random() * 1000));
}
@Test
public void random() {
Random random = new Random();
System.out.println("随机数:" + random.nextInt());
System.out.println("随机 0 - 1000 之间:" + random.nextInt(1000));
}
@Test
public void threadLocalRandom() {
ThreadLocalRandom random = ThreadLocalRandom.current();
System.out.println("随机数:" + random.nextInt());
System.out.println("随机 0 - 1000 之间:" + random.nextInt(1000));
}
@Test
public void splittableRandom() {
SplittableRandom random = new SplittableRandom();
System.out.println("随机数:" + random.nextInt());
System.out.println("随机 0 - 1000 之间:" + random.nextInt(1000));
}
UUID
这里所说的UUID是一个泛指,愿意是想表述一种可应用于随机不重复ID的实现,也同样列举了几种常见的实现,参考代码如下。
@Test
public void uuid() {
System.out.println("UUID:" + UUID.randomUUID().toString());
}
@Test
public void hutool() {
System.out.println("randomUUID:" + IdUtil.randomUUID());
System.out.println("simpleUUID:" + IdUtil.simpleUUID());
System.out.println("fastSimpleUUID:" + IdUtil.fastSimpleUUID());
for (int i = 1 ; i <= 5 ; i++) {
System.out.println("objectId:" + IdUtil.objectId());
}
Snowflake snowflake = IdUtil.getSnowflake();
for (int i = 1 ; i <= 5 ; i++) {
System.out.println("snowflake:" + snowflake.nextId());
}
}
@Test
public void mybatisPlus() {
for (int i = 1 ; i <= 5 ; i++) {
System.out.println("getId:" + IdWorker.getId());
}
System.out.println("get32UUID:" + IdWorker.get32UUID());
System.out.println("getTimeId:" + IdWorker.getTimeId());
}
其它说明
(1)UUID是36位长度的不重复字符串,中间的“-”在很多场景下也会被替换为空白,拥有无规律,代码简单,唯一,效率高,安全性高(伪造难)等优点,但同时存储成本稍大,无排序,不可读等缺点;
(2)hutool是一款国产的工具库,囊括的功能范围较广,更适合国人一些常规功能需求范围,IdUtil提供了随机UUID、简单UUID和雪花ID等, 具体如下:
A. randomUUID的结果等同于JDK的UUID;
B. simpleUUID的结果等于JDK的UUID去除“-”;
C. fastSimpleUUID的结果等于simpleUUID;
D. objectId的结果为24位字母数字组合的随机文本,且最后一位数位16进制增长的0-9-a-f,再增长时倒数第二位进1(类似JPA种的UUID);
E. snowflake的结果为19位数字的文本,多次调用累加1的增长,个人建议在涉及一些外部系统交互时可以在此ID的前缀增加系统标识;
(3)mybatis plus中提供了IdWorker工具类,旨在为数据的保存提供ID取值的实现,列举3个函数的实现,参考如下:
A. getId的结果等同于hutool中IdUtil.snowflake,19位数字,累加1的增长;
B. get32UUID的结果等同于hutool中IdUtil.simpleUUID的实现,32位字母数字组合;
C. getTimeId的结果是getMillisecond + getId的结果,表示当前年月日时分秒毫秒 + 19位雪花ID;
(4)本次主要是以Java代码的方式来整理实现,同样需要读者更多的去实践总结,至于数据库层面的序列、自增ID、rowid、uuid、Redis中的自增等等不在范围内;
(5)输出示例结果:
getId:1651820597659467778
getId:1651820597659467779
getId:1651820597659467780
getId:1651820597659467781
getId:1651820597659467782
get32UUID:99192bc42f5e28da6553e4c001b101e3
getTimeId:202304281328144901651820597659467783
randomUUID:afc2ed1f-1dcb-48e1-9839-e83372921a02
simpleUUID:4cd05c98419a45c7b97becff0fbfa217
fastSimpleUUID:7ad24e015d7e419a986645d452435063
objectId:644b59706b41f501b985da11
objectId:644b59706b41f501b985da12
objectId:644b59706b41f501b985da13
objectId:644b59706b41f501b985da14
objectId:644b59706b41f501b985da15
snowflake:1651820616286371840
snowflake:1651820616286371841
snowflake:1651820616286371842
snowflake:1651820616286371843
snowflake:1651820616286371844
随机数:1196258473
随机 0 - 1000 之间:837
随机数 0 - 1 之间:0.867309765296692
随机数 0 - 1000 之间:516
UUID:ee3e60d8-deba-473e-ba52-80a5a17dcb58
随机数:1493133155
随机 0 - 1000 之间:225
随机数:-1042200000
随机 0 - 1000 之间:381
(6)参考代码地址:chendd-examples: chendd-examples - Gitee.com;
(7)Github上的开源项目Leaf是美团技术团队退出的高性能分布式ID生成方式,可用于弥补各种ID的缺点,参考地址:“GitHub - Meituan-Dianping/Leaf: Distributed ID Generate Service”;
分享随机数和唯一ID的工具类欢迎来到陈冬冬的个人经验分享平台https://www.chendd.cn/blog/article/1651782163204202497.html