前言
在 Java 开发中,生成随机字符串是一个常见需求,无论是验证码、临时密码、唯一标识符还是测试数据,都需要高效可靠的随机字符串生成方案。Hutool 作为一个强大的 Java 工具库,其 RandomUtil 类提供了丰富且易用的随机字符串生成方法,能够满足各种复杂场景下的需求。本文将深入探讨不同场景下的随机字符串生成技巧,帮助开发者快速掌握这一实用技能。
一、概述
1.1 工具简介
原生 Java 的随机数生成机制,其设计哲学是通用性和安全性,但在多线程环境下使用 java.util.Random,并且多个线程共享同一个实例,那么可能会遇到性能瓶颈甚至随机序列冲突的问题,因为 Random 内部使用原子种子更新,在高并发下会竞争。而 Hutool 的 RandomUtil 在设计之初就考虑到了这一点,作为专门用于生成各类随机数据的工具类,底层默认基于 SecureRandom 实现加密级强随机数生成,既避免了原生 Java 手动封装的繁琐代码,又解决了普通 Random 线程不安全、随机序列可预测的安全隐患,能大幅提升验证码、临时密码、测试数据等场景的开发效率。它完全封装了随机数生成的底层细节,开箱即用,无需手动管理随机源、字符池等重复逻辑,同时兼顾了线程安全与高并发场景下的性能表现。
API 文档:plus.hutool.cn/apidocs/cn/...
1.2 引入依赖
在使用 Hutool 工具之前,需要将 Hutool 添加到项目的依赖中。如果使用 Maven 构建项目,可以在 pom.xml 文件中添加以下依赖:
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<!-- 请检查最新版本,可以根据实际需要进行调整 -->
<version>5.8.40</version>
</dependency>
Hutool-all 是一个 Hutool 的集成打包产品,由于考虑到"懒人"用户及分不清各个模块作用的用户,"无脑"引入 hutool-all 模块是快速开始和深入应用的最佳方式。如果你想像 SpringBoot 一样引入 Hutool,再由子模块决定用到哪些模块,你可以在父模块中加入:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-bom</artifactId>
<version>${hutool.version}</version>
<type>pom</type>
<!-- 注意这里是import -->
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
然后再在子模块中就可以引入自己需要的模块了:
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
</dependencies>
二、基础随机数操作方法
2.1 基础数值类随机方法
2.1.1 整数随机
可以轻松创建指定范围内的整数值。
| 方法 |
简要说明 |
| randomInt() |
生成一个随机整数,范围在 [0, Integer.MAX_VALUE) |
| randomInt(int limit) |
生成 [0, limit) 范围内的随机整数,不包含最大值 |
| randomInt(int min, int max) |
获得指定范围内的随机数,包含最小值、不包含最大值 |
| randomInt(int min, int max, boolean includeMin, boolean includeMax) |
精确控制边界,生成范围内的随机整数 |
| randomInts(int length) |
生成随机 int 数组 |
System.out.println("随机生成任意整数:" + RandomUtil.randomInt());
System.out.println("生成 [0, 100) 的随机整数:" + RandomUtil.randomInt(0, 100));
System.out.println("生成 [10, 100) 的随机整数(包含100):" + RandomUtil.randomInt(10, 100));
System.out.println("生成长度为 5 的随机 int 数组:" + Arrays.toString(RandomUtil.randomInts(5)));
2.1.2 长整型随机
| 方法 |
简要说明 |
| randomLong() |
生成长整型随机数 |
| randomLong(int limit) |
生成 [0, limit) 范围内的随机长整数 |
| randomLong(int min, int max) |
生成 [min, max) 范围内的随机长整数 |
| randomLong(int min, int max, boolean includeMin, boolean includeMax) |
精确控制边界,生成范围内的随机长整数 |
System.out.println("随机长整数" + RandomUtil.randomLong());
System.out.println("生成 [0, 1000) 的随机长整数:" + RandomUtil.randomLong(1000));
System.out.println("生成 [500, 1000) 的随机长整数:" + RandomUtil.randomLong(500, 1000));
System.out.println("生成 [1000, 2000) 的随机长整数:" + RandomUtil.randomLong(1000, 2000));
2.1.3 浮点数随机
同样支持浮点数区间内取值。
| 方法 |
简要说明 |
| randomFloat() |
生成浮点型随机数 |
| randomFloat(float limit) |
生成 [0, limit) 范围内的随机浮点数 |
| randomFloat(float min, float max) |
生成 [min, max) 范围内的随机浮点数 |
2.1.4 双精度随机
| 方法 |
简要说明 |
| randomDouble() |
生成双精度型随机数 |
| randomDouble(double limit) |
生成 [0, limit) 范围内的随机双精度数 |
| randomDouble(double min, double max) |
生成 [min, max) 范围内的随机双精度数 |
| randomDouble(double min, double max, int scale, RoundingMode roundingMode) |
指定精度与舍入 |
| randomDouble(double limit, int scale, RoundingMode roundingMode) |
|
System.out.println("生成随机浮点数" + RandomUtil.randomDouble());
System.out.println("生成 [0, 100) 的随机浮点数:" + RandomUtil.randomDouble(100));
System.out.println("生成 [10, 20) 的随机浮点数:" + RandomUtil.randomDouble(10, 20));
System.out.println("随机double保留2位:" + RandomUtil.randomDouble(1, 10, 2, RoundingMode.HALF_UP));
2.1.5 布尔值随机
| 方法 |
简要说明 |
| randomBoolean() |
生成随机的 true 或 false,50% 概率 |
System.out.println("随机布尔:" + RandomUtil.randomBoolean());
2.2 高精度整数随机
| 方法 |
简要说明 |
| randomBigDecimal() |
|
| randomBigDecimal(BigDecimal limit) |
|
| randomBigDecimal(BigDecimal min, BigDecimal max) |
|
RandomUtil.randomBigDecimal();
RandomUtil.randomBigDecimal(BigDecimal.valueOf(100));
RandomUtil.randomBigDecimal(BigDecimal.valueOf(10), BigDecimal.valueOf(20));
2.3 字符串随机
Hutool 的 RandomUtil 类封装了多种随机字符串生成方法,相比 Java 原生实现更加简洁高效,能够按照设定长度生成字母数字混合字符串。这是业务开发中最常用的一类方法,覆盖绝大多数随机文本场景:
| 方法 |
简要说明 |
| randomString(int length) |
生成指定长度、包含数字和字符的随机字符串 |
| randomString(String source, int length) |
自定义字符集生成指定长度的随机字符串 |
| randomStringUpper(int length) |
获得一个随机的字符串(只包含数字和大写字符) |
| randomStringLowerWithoutStr(int length, String elemData) |
包含数字和小写字符的随机字符串,排除指定字符 |
| randomStringWithoutStr(int length, String elemData) |
包含数字和大写字符的随机字符串,排除指定字符 |
| randomNumber() |
只包含数字的随机字符串 |
| randomNumbers(int length) |
生成指定长度的纯数字**的随机字符串 |
String randomStr = RandomUtil.randomString(10);
System.out.println("基本随机字符串:" + randomStr);
String customString = RandomUtil.randomString("ab", 8);
System.out.println("自定义字符集:" + customString);
String upperCase = RandomUtil.randomStringUpper(8);
System.out.println("只包含大写字母和数字:" + upperCase);
String clearString = RandomUtil.randomStringWithoutStr(6, "01O");
System.out.println("排除易混淆字符:" + clearString);
String numbers = RandomUtil.randomNumbers(6);
System.out.println("只包含数字:" + numbers);
2.4 字节数组随机
| 方法 |
简要说明 |
| randomChar() |
随机从「字母+数字」中随机获取单个字符 |
| randomChar(String source) |
从指定字符串随机获取单个字符 |
| randomBytes(int length) |
生成指定长度的随机字节数组 |
// 从指定字符串中产生一个随机字符
System.out.println(RandomUtil.randomChar("smart"));
三、高级随机数操作方法
3.1 随机日期
| 方法 |
简要说明 |
| randomDate(Date baseDate, DateField dateField, int min, int max) |
自定义基准日期,按年/月/日偏移,获取范围内的随机日期 |
| randomDay(int min, int max) |
以今天为基准,min、max是天数偏移量 |
// 生成最近3天内的随机日期
DateTime randomDate = RandomUtil.randomDay(-3, 0);
System.out.println(randomDate);
// 基于特定字段生成随机日期
DateTime base = DateUtil.date();
DateTime randomTime = RandomUtil.randomDate(base, DateField.HOUR, -12, 0);
System.out.println(randomTime);
3.2 随机选取
| 方法 |
简要说明 |
| randomEle |
随机选择一个元素 |
| randomEleList |
随机选择多个不重复元素(列表形式) |
| randomEles |
随机选择多个元素(元素可能重复) |
| randomEleSet |
随机选择多个不重复元素 |
List<Integer> itemList = CollUtil.newArrayList(1, 2, 3, 4, 5, 6);
Integer randomItem = RandomUtil.randomEle(itemList);
System.out.println("随机选择一个元素:" + randomItem);
Set<Integer> uniqueRandomItems = RandomUtil.randomEleSet(itemList, 3);
System.out.println("随机选择多个不重复元素:" + uniqueRandomItems);
List<Integer> randomItems = RandomUtil.randomEles(itemList, 3);
System.out.println("随机选择多个元素(可能重复):" + randomItems);
List<Integer> uniqueRandomList = RandomUtil.randomEleList(itemList, 3);
System.out.println("随机选择多个不重复元素(列表形式):" + uniqueRandomList);
3.3 权重随机
权重随机生成器,传入带权重的对象,根据设定的权重值返回对应对象。权重值越大,被选中的概率越高。权重为 50 的对象,被选中概率是权重为 20 的对象的 2.5 倍。
| 方法 |
简要说明 |
| weightRandom(WeightRandom\[\] weightObjs) |
|
| weightRandom(Iterable weightObjs) |
|
有时候随机不是完全均等的,我们需要带权重的随机。比如,一个抽奖活动(一等奖概率1%、二等奖概率5%、三等奖概率10%、参与奖概率84%),根据预设的权重随机挑选一个。
// 创建权重随机对象
WeightRandom<String> weightRandom = new WeightRandom<>();
weightRandom.add("一等奖", 1.0); // 1%概率
weightRandom.add("二等奖", 5.0); // 5%概率
weightRandom.add("三等奖", 10.0); // 10%概率
weightRandom.add("谢谢参与", 84.0); // 84%概率
System.out.println("进行随机选择:" + weightRandom.next());
// 对象 + 权重数组快捷创建
List<WeightRandom.WeightObj<String>> list = new ArrayList<>();
list.add(new WeightRandom.WeightObj<>("一等奖", 1.0));
list.add(new WeightRandom.WeightObj<>("二等奖", 5.0));
list.add(new WeightRandom.WeightObj<>("三等奖", 10.0));
list.add(new WeightRandom.WeightObj<>("谢谢参与", 84.0));
System.out.println("按权重随机返回:" + RandomUtil.weightRandom(list).next());
四、安全随机数生成解析
| 方法 |
简要说明 |
| getRandom() |
获取普通随机数生成器(高性能) |
| getSecureRandom() |
获取安全随机数生成器(默认算法) |
| getSecureRandom(byte\[\] seed) |
获取指定种子的安全随机数 |
| getSHA1PRNGRandom(byte\[\] seed) |
获取SHA1PRNG算法安全随机数 |
| getSecureRandomStrong() |
获取最强安全随机数生成器(可能阻塞) |
@Test
public void getSecureRandomTest() {
// 使用安全随机数生成器生成更安全的令牌
SecureRandom secureRandom = RandomUtil.getSecureRandom();
String randomString = RandomUtil.randomString(RandomUtil.BASE_CHAR_NUMBER, 32);
System.out.println(randomString);
}
五、总结
RandomUtil 是 Hutool 中非常实用的工具类,能够满足大多数随机数生成的需求。它的 API 设计简洁,使用方便,适合在 Java 项目中快速实现随机数相关的功能。如果需要更复杂的随机数生成逻辑,可以结合 Java 原生的 Random 类或 ThreadLocalRandom 类来实现。