当前位置:   article > 正文

不相等 多次随机数_Java随机数生成器知多少?

dsi.util

本文由牛旦教育原创。

0.导言

本文主要是介绍在Java中生成随机数的不同选择和方式。实际应用中根据自己的需要选择。

12b555b608bf39bebb617024b0e19077.png

1.Java API

在Java本身自带的API中,为我们提供了几种方式来获得随机数。我们来看下。

1.1. java.lang.Math

Math类的random方法将返回一个范围为0.0(包括0.0)到1.0(不包括1.0)的双精度值。看看该如何使用它来获得一个在给定的范围(最小和最大值间)内定义的随机数:

int randomWithMathRandom = (int) ((Math.random() * (max - min)) + min);

这行代码的意思为为,我们用两个整数,表示结果的随机数的取值范围在min和max之间。直接在JShell中简要演示这个实现,我这里参考如下(每次的结果可能都不同):

8092f7a022d5552192b79462e74075a8.png

1.2. java.util.Random

在Java 1.7之前,最流行的生成随机数的方法是使用nextInt。有两种途径使用使用这个方法,即带参数和不带参数。无参数调用以近似相等的概率返回任何int值。所以很有可能得到负数,参考代码如下:

Random random = new Random();
int randomWithNextInt = random.nextInt();

我在本机JShell中运行结果如下:

15c01d354a3d082492f689a881ab8f19.png

如果使用绑定参数的netxInt方法(参数对返回值进行范围约定了),我们将得到一个范围内的数字,示例如下:

int aVal = random(ival) ;

注意:这类需要主要,ival值必须是大于0,返回值在0和ival之间,但不包含ival;若参数小于等于0,则会报错: java.lang.IllegalArgumentException.

演示:那么要想得到一个在min和max之间的整数,我在JShell中演示结果如下:

692c1f703629e9e285a423991c555031.png

Java 8引入了新的ints方法,此方法返回java.util.stream.IntStream。IntStream,LongStream,DoubleStream等用于操作流中的数据,同时提供了相应的静态方法来初始化它们自己。让我们看看如何使用它们。

没有参数的ints方法返回一个无限的int流,其代码示例如下:

IntStream unlimitedIntStream = random.ints();

也可以传入一个参数限制流大小,示例如下:

IntStream limitedIntStream = random.ints(streamSize);

当然,我们可以设置最大和最小值来生成带范围的int流,示例如下:

IntStream limitedIntStreamWithinARange = random.ints(streamSize, min, max);

具体用户可以查看Java API参考。

1.3. java.util.concurrent.ThreadLocalRandom

Java 1.7之后,为我们带来了一种通过ThreadLocalRandom类来生成随机数的更高效的新方法。这个类与随机类有三个重要区别:

  • ü 不需要显式地初始化ThreadLocalRandom的新实例。这有助于避免创建大量无用实例和浪费垃圾收集器时间的错误;
  • ü 不能为ThreadLocalRandom设置种子,这会导致一个实际的问题。如果我们需要设置种子,那么我们应该避免使用这种产生随机数的方式;
  • ü Random (随机)类在多线程环境中表现不佳。

下面看看其工作方式:

int randomWithThreadLocalRandomInARange = ThreadLocalRandom.current().nextInt(min, max);

使用Java 8或更高版本,我们就有了新的可能性。

首先,nextInt方法有两种变体:

int randomWithThreadLocalRandom = ThreadLocalRandom.current().nextInt();
int randomWithThreadLocalRandomFromZero = ThreadLocalRandom.current().nextInt(max);

其次,更重要的是,我们可以使用ints方法:

IntStream streamWithThreadLocalRandom = ThreadLocalRandom.current().ints();

1.4. java.util.SplittableRandom

Java 8还给我们带来了一个非常快的生成器——SplittableRandom类。

正如我们在JavaDoc中看到的,这是一个用于并行计算的生成器。重要的是要知道实例不是线程安全的。所以,我们在使用这个类时必须小心。

还提供了nextInt和ints方法。使用nextInt,我们可以直接使用两个参数设置最高最低范围来调用:

SplittableRandom splittableRandom = new SplittableRandom();
int randomWithSplittableRandom = splittableRandom.nextInt(min, max);

这种方法可以检查max参数是否大于min,否则会得到一个IllegalArgumentException。但是,它不能检查我们是用正数还是负数。所以,参数都可以是任何负的。此外,我们还提供了一参和零参的调用。它们的工作方式和我们之前描述的一样。

也有ints方法。这意味着我们可以很容易地获得一个int流。必须清楚,使用中可以选择一个有限的或无限的流。对于一个有限的流,我们可以设置最高最低的数字生成范围约束:

IntStream limitedIntStreamWithinARangeWithSplittableRandom = splittableRandom.ints(streamSize, min, max);

1. .5. java.security.SecureRandom

如果我们有安全敏感的应用程序,或说安全要求高的,推荐考虑使用SecureRandom。这是一个加密的强生成器。默认构造的实例不使用加密随机种子。所以,我们应该:

  • ü 设置种子-但种子将是不可预测的;
  • ü 设置java.util.secureRandomSeed系统属性为true;

这个类继承自java.util.Random。因此,我们可以使用上面看到的所有方法。例如,如果我们需要获取任何int值,那么可调用没有参数的nextInt:

SecureRandom secureRandom = new SecureRandom();
int randomWithSecureRandom = secureRandom.nextInt();

另一方面,如果我们需要设置范围,我们可以调用带参数的方法:

int randomWithSecureRandomWithinARange = secureRandom.nextInt(max - min) + min;

必须当心:如果参数不大于0,这种使用方法会抛出IllegalArgumentException。

2.第三方API

正如我们所看到的,Java为我们提供了许多生成随机数的类和方法。然而,还有第三方提供的API服务于此目的。我们来看看其中的一些。

2.1. org.apache.commons.math3.random.RandomDataGenerator

在Apache commons项目的commons数学库中有很多生成器。最简单,也可能最有用的就是RandomDataGenerator。它使用Well19937c(https://en.wikipedia.org/wiki/Well_equidistributed_long-period_linear)算法进行随机生成。但是,我们可以提供我们的算法实现。

让我们看看如何使用它。首先,我们必须添加依赖:

org.apache.commons

commons-math3

3.6.1

可以在Maven Central上找到commons-math3的最新版本。

导入项目后,就可以开始使用它们工作了,示例如下:

RandomDataGenerator randomDataGenerator = new RandomDataGenerator();
int randomWithRandomDataGenerator = randomDataGenerator.nextInt(min, max);

2.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

这是最快的随机数生成器实现之一。它是由米兰大学信息科学系开发的。

该库也可以在Maven中央存储库中使用。因此,让引用时可以如下添加依赖:

it.unimi.dsi

dsiutils

2.6.0

这个生成器继承自java.util.Random。但是,如果我们看一下JavaDoc,就会发现只有一种方法可以使用它——nextInt方法。最重要的是,此方法仅可用于零参数和单参数调用。其他任何调用都将直接使用java.util.Random随机方法。

例如,如想要得到一个范围内的随机数,你可以这样写:

XoRoShiRo128PlusRandom xoroRandom = new XoRoShiRo128PlusRandom();
int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt(max - min) + min;

3.最后

通过本文,我们知道了有几种实现随机数生成的方法。然而,没有最好的方法。因此,我们应该选择最适合我们需要的。

你还知道有哪些有趣的随机数生成类,分享一下吧.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/106915
推荐阅读
相关标签
  

闽ICP备14008679号