返回介绍

Java8 中的 java.util.Random 类

发布于 2025-02-26 22:54:39 字数 3593 浏览 0 评论 0 收藏 0

在 Java8 中 java.util.Random 类的一个非常明显的变化就是新增了返回随机数流(random Stream of numbers) 的一些方法。

下面的代码是创建一个无穷尽的 double 类型的数字流,这些数字在 0(包括 0)和 1(不包含 1)之间。

    Random random = new Random();
    DoubleStream doubleStream = random.doubles();

下面的代码是创建一个无穷尽的 int 类型的数字流,这些数字在 0(包括 0)和 100(不包括 100)之间。

    Random random = new Random();
    IntStream intStream = random.ints(0, 100);

那么这些无穷尽的数字流用来做什么呢?接下来,我通过一些案例来分析。记住,这些无穷大的数字流只能通过某种方式被截断(limited)。

示例 1:创建 10 个随机的整数流并打印出来:

    intStream.limit(10).forEach(System.out::println);

示例 2:创建 100 个随机整数:

    List<Integer> randomBetween0And99 = intStream
                                       .limit(100)
                                       .boxed()
                                       .collect(Collectors.toList());

对于高斯伪随机数(gaussian pseudo-random values)来说,random.doubles() 方法所创建的流不能等价于高斯伪随机数,然而,如果用 java8 所提供的功能是非常容易实现的。

    Random random = new Random();
    DoubleStream gaussianStream = Stream.generate(random::nextGaussian).mapToDouble(e -> e);

这里,我使用了 Stream.generate api,并传入 Supplier 类的对象作为参数,这个对象是通过调用 Random 类中的方法 nextGaussian() 创建另一个高斯伪随机数。

接下来,我们来对 double 类型的伪随机数流和 double 类型的高斯伪随机数流做一个更加有意思的事情,那就是获得两个流的随机数的分配情况。预期的结果是:double 类型的伪随机数是均匀的分配的,而 double 类型的高斯伪随机数应该是正态分布的。

通过下面的代码,我生成了一百万个伪随机数,这是通过 java8 提供的 api 实现的:

    Random random = new Random();
    DoubleStream doubleStream = random.doubles(-1.0, 1.0);
    LinkedHashMap<Range, Integer> rangeCountMap = doubleStream.limit(1000000)
        .boxed()
        .map(Ranges::of)
        .collect(Ranges::emptyRangeCountMap, (m, e) -> m.put(e, m.get(e) + 1), Ranges::mergeRangeCountMaps);

    rangeCountMap.forEach((k, v) -> System.out.println(k.from() + "\t" + v));

代码的运行结果如下:

    -1      49730
    -0.9    49931
    -0.8    50057
    -0.7    50060
    -0.6    49963
    -0.5    50159
    -0.4    49921
    -0.3    49962
    -0.2    50231
    -0.1    49658
    0       50177
    0.1     49861
    0.2     49947
    0.3     50157
    0.4     50414
    0.5     50006
    0.6     50038
    0.7     49962
    0.8     50071
    0.9     49695

为了类比,我们再生成一百万个高斯伪随机数:

    Random random = new Random();
    DoubleStream gaussianStream = Stream.generate(random::nextGaussian).mapToDouble(e -> e);
    LinkedHashMap<Range, Integer> gaussianRangeCountMap =
        gaussianStream
                .filter(e -> (e >= -1.0 && e < 1.0))
                .limit(1000000)
                .boxed()
                .map(Ranges::of)
                .collect(Ranges::emptyRangeCountMap, (m, e) -> m.put(e, m.get(e) + 1), Ranges::mergeRangeCountMaps);

    gaussianRangeCountMap.forEach((k, v) -> System.out.println(k.from() + "\t" + v));

上面代码输出的结果恰恰与我们预期结果相吻合,即:double 类型的伪随机数是均匀的分配的,而 double 类型的高斯伪随机数应该是正态分布的。

用伪随机数所得的结果:

用高斯伪随机数所得的结果:

附:完整代码可点击 这里 获取

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文