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);
            }
        }

    }
}