Hutool之RandomUtil:随机数生成的终极利器

前言

  在 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 文件中添加以下依赖:

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,再由子模块决定用到哪些模块,你可以在父模块中加入:

xml 复制代码
<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>

  然后再在子模块中就可以引入自己需要的模块了:

xml 复制代码
<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 数组
java 复制代码
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) 精确控制边界,生成范围内的随机长整数
java 复制代码
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)
java 复制代码
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% 概率
java 复制代码
 System.out.println("随机布尔:" + RandomUtil.randomBoolean());

2.2 高精度整数随机

方法 简要说明
randomBigDecimal()
randomBigDecimal(BigDecimal limit)
randomBigDecimal(BigDecimal min, BigDecimal max)
java 复制代码
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) 生成指定长度的纯数字**的随机字符串
java 复制代码
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) 生成指定长度的随机字节数组
java 复制代码
// 从指定字符串中产生一个随机字符
System.out.println(RandomUtil.randomChar("smart"));

三、高级随机数操作方法

3.1 随机日期

方法 简要说明
randomDate(Date baseDate, DateField dateField, int min, int max) 自定义基准日期,按年/月/日偏移,获取范围内的随机日期
randomDay(int min, int max) 以今天为基准,min、max是天数偏移量
java 复制代码
// 生成最近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 随机选择多个不重复元素
java 复制代码
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%),根据预设的权重随机挑选一个。

java 复制代码
// 创建权重随机对象
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() 获取最强安全随机数生成器(可能阻塞)
java 复制代码
@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 类来实现。

相关推荐
小小张说故事1 小时前
Python 多线程为什么跑不快?asyncio 入门指南:异步并发从零上手
后端·python
明月_清风1 小时前
数据进入平台后怎么处理?一文搞懂 ETL
大数据·后端·数据分析
初学AI的小高1 小时前
LangGraph断点恢复与幂等执行实战
后端·架构
欧西1 小时前
AI全栈安全Agent平台(九):自动化测试用例生成引擎实战
后端
BBmmo1 小时前
我的 Java 学习笔记 · 第 7 篇:泛型与通配符
java
imDwAaY1 小时前
6篇文章讲清楚Git:Git 远程协作:fetch、pull、push 到底有什么区别?(3/6)
git·后端
金銀銅鐵1 小时前
[Java] 通过行为参数化传递代码
后端·函数式编程
浪遏1 小时前
D2C 系统架构复盘:从设计稿到代码,我们踩过的坑和最终方案
前端·javascript·后端