JDK17版本
# JDK17版本
# 1、增强版伪随机数生成器
在JDK17版本之前 我们要生成随机数据主要通过:
java.util.Random
java.security.SecureRandom
这两个实现都有局限性:
Random生成的随机数有可预测性:
java.util.Random 使用的是一个线性同余生成器(LCG)算法,Random 的输出是完全可预测的,如果我们知道种子和算法,完全可以生成相同的随机序列。
这在需要高安全性的随机数生成(如加密)时是不合适的。
java.security.SecureRandom 是 Java 提供的一个用于生成加密强度随机数的类,专门为需要高安全性的应用场景设计,比如加密、安全令牌生成、会话密钥以及数字签名应用。
SecureRandom 优劣势分析:
优势 | 劣势 |
---|---|
安全性高: SecureRandom设计用于提供加密强度的随机数生成,这意味着它生成的随机数更难以预测,对于安全敏感的应用至关重要。它通常基于操作系统提供的强随机数生成器(例如 /dev/urandom 在Unix-like系统中),或者使用硬件随机数生成器(如果可用),以确保高度的不可预测性。 | 性能问题: 由于SecureRandom强调安全性,它的生成速度可能比非安全的随机数生成器(如java.util.Random)慢。特别是在大量需要随机数的场景下,这种性能差异可能会成为瓶颈。 |
可配置性: 用户可以选择不同的随机数生成算法,Java提供了多种算法供选择,比如SHA1PRNG、NativePRNG等,可以根据应用场景的安全需求和性能要求来定制。 | 资源消耗: 特别是当依赖于硬件随机数生成器时,如果硬件生成随机数的速度较慢或资源紧张,可能会对系统整体性能产生影响。 |
JDK17版本引入了 增强版伪随机数生成器
RandomGenerator 接口:
获取RandomGenerator 实例:
- 默认实现 RandomGenerator.getDefault()
- 使用RandomGenerator.of(String name)获取特定的随机数生成器,name 为预定义的生成器名称。
- 使用RandomGeneratorFactory 工厂 获取RandomGenerator 实例
代码示例:
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
public class TestA {
public static void main(String[] args) {
// 获取默认的 随机数生成器
RandomGenerator randomGenerator1 = RandomGenerator.getDefault();
// 获取指定的 随机数生成器
RandomGenerator randomGenerator2 = RandomGenerator.of("Xoshiro256PlusPlus");
// 使用 随机数生成工厂RandomGeneratorFactory 获取默认的随机数生成器
RandomGeneratorFactory<RandomGenerator> aDefault = RandomGeneratorFactory.getDefault();
RandomGenerator randomGenerator3 = aDefault.create();
// 使用 随机数生成工厂RandomGeneratorFactory 获取指定的随机数生成器
RandomGeneratorFactory<RandomGenerator> factory = RandomGeneratorFactory.of("Xoshiro256PlusPlus");
RandomGenerator randomGenerator4 = factory.create();
// 打印工厂中所有可用的随机数生成器
RandomGeneratorFactory.all().forEach((item)->System.out.println(item.name()));
}
}
RandomGeneratorFactory工厂中所有可用的随机数生成器如下:
随机数生成器名称 | 版本 | 使用算法 | 特性 |
---|---|---|---|
Random | JDK1.0 | 线性同余生成器 (LCG) | 简单、快速,但周期短且质量较低 |
SecureRandom | JDK1.1 | 依赖于底层平台提供的安全随机数生成算法 | 高质量、安全的随机数,适用于加密等安全需求,但是性能一般 |
L32X64MixRandom | JDK17 | LXM系列算法,基于线性同余和XorShift | 高性能、适合并行计算,适用于普通用途 |
L128X128MixRandom | JDK17 | LXM系列算法,基于线性同余和XorShift | 增强版L32X64,具有更长的周期和更高的质量 |
L64X128MixRandom | JDK17 | LXM系列算法,基于线性同余和XorShift | 适用于需要中等周期和质量的应用 |
L128X1024MixRandom | JDK17 | LXM系列算法,基于线性同余和XorShift | 超长周期,高质量,适用于高需求应用 |
L64X128StarStarRandom | JDK17 | LXM系列算法,基于线性同余和XorShift | 类似L64X128,但具有不同的混合策略 |
Xoshiro256PlusPlus | JDK17 | Xoshiro256++ 算法 | 高速、长周期,适用于高性能计算 |
L64X256MixRandom | JDK17 | LXM系列算法,基于线性同余和XorShift | 提供更长的周期,适用于需要更高质量随机数的场景 |
Xoroshiro128PlusPlus | JDK17 | Xoroshiro128++ 算法 | 高速、适合资源有限的环境 |
L128X256MixRandom | JDK17 | LXM系列算法,基于线性同余和XorShift | 非常长的周期,适用于对随机数质量要求极高的场景 |
SplittableRandom | JDK17 | 基于64位乘法哈希算法 | 高性能、线程安全,适合并行计算 |
L64X1024MixRandom | JDK17 | LXM系列算法,基于线性同余和XorShift | 超长周期,适用于需要极高质量随机数的场景 |
比较常用的方法
- 生成随机数:例如 nextInt()、nextInt(0, 100)、nextLong()
- 生成随机数流:例如 ints()、longs(),这些方法返回的是一个 Stream,对于生成大量随机数比较有用。
代码示例:
import java.util.random.RandomGenerator;
public class TestA {
public static void main(String[] args) {
// 获取默认的 随机数生成器
RandomGenerator randomGenerator = RandomGenerator.getDefault();
// 范围是 Integer.MIN_VALUE(-2^31)到 Integer.MAX_VALUE(2^31 - 1)之间的所有整数。
int i = randomGenerator.nextInt();
System.out.println(i);
// 生成 [0,100) 之间的整数 包含0,不包含100
int i1 = randomGenerator.nextInt(100);
System.out.println(i1);
// 生成 [50,100) 之间的整数 包含50,不包含100
int i2 = randomGenerator.nextInt(50,100);
System.out.println(i2);
// 获取无限随机数流 并截取前10个 默认的int类型最大范围
randomGenerator.ints().limit(10).forEach(System.out::println);
// 获取包含10个随机数的流 默认的int类型最小范围
randomGenerator.ints(10).forEach(System.out::println);
// 生成一个无限的范围在[10, 20)的随机数流,并截取前10个,直接打印
randomGenerator.ints(10, 20).limit(10).forEach(System.out::println);
}
}
# 2、增强版Switch
防止的Fall-through新写法 (守卫模式)
case xxx -> 可以不用谢break; 也能防止穿透模式匹配(类型模式、空模式、常量模式)
测试这个Demo 需要稍微新点版本的 IDEA 我用的IntelliJ IDEA 2023.1
public class TestA {
public static void main(String[] args) {
Object[] objects = {"Java", 123, "C#", "PHP", 6.66, "DeepJava"};
for (Object obj : objects) {
switch (obj) {
case Integer intR -> System.out.println("整数型:" + intR);
case Float floatR -> System.out.println("浮点型:" + floatR);
case Double doubleR -> System.out.println("双精度浮点数:" + doubleR);
case String str && str.length() > 5 -> System.out.println("长度超过5的字符串:" + str);
case String str -> System.out.println("短字符串:" + str);
case null -> System.out.println("为空值");
default -> System.out.println("其他类型:" + obj);
}
}
}
}