这些Java中的随机数生成工具

0.导言

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

这些Java中的随机数生成工具/类,总有一款适合你


1.Java API

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

1.1. java.lang.Math

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

<code>int randomWithMathRandom = (int) ((Math.random() * (max - min)) + min);/<code>

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


这些Java中的随机数生成工具/类,总有一款适合你

1.2. java.util.Random

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

<code>Random random = new Random();/<code>
<code>int randomWithNextInt = random.nextInt();/<code>

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


这些Java中的随机数生成工具/类,总有一款适合你

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

<code>int aVal = random(ival) ;/<code>

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

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


这些Java中的随机数生成工具/类,总有一款适合你

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

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

<code>IntStream unlimitedIntStream = random.ints();/<code>

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

<code>IntStream limitedIntStream = random.ints(streamSize);/<code>

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

<code>IntStream limitedIntStreamWithinARange = random.ints(streamSize, min, max);/<code>

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

1.3. java.util.concurrent.ThreadLocalRandom

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

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

下面看看其工作方式:

<code>int randomWithThreadLocalRandomInARange = ThreadLocalRandom.current().nextInt(min, max);/<code>

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

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

<code>int randomWithThreadLocalRandom = ThreadLocalRandom.current().nextInt();/<code>
<code>int randomWithThreadLocalRandomFromZero = ThreadLocalRandom.current().nextInt(max);/<code>

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

<code>IntStream streamWithThreadLocalRandom = ThreadLocalRandom.current().ints();/<code>

1.4. java.util.SplittableRandom

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

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

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

<code>SplittableRandom splittableRandom = new SplittableRandom();/<code>
<code>int randomWithSplittableRandom = splittableRandom.nextInt(min, max);/<code>

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

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

<code>IntStream limitedIntStreamWithinARangeWithSplittableRandom = splittableRandom.ints(streamSize, min, max);/<code>

1. .5. java.security.SecureRandom

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

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

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

<code>SecureRandom secureRandom = new SecureRandom();/<code>
<code>int randomWithSecureRandom = secureRandom.nextInt();/<code>

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

<code>int randomWithSecureRandomWithinARange = secureRandom.nextInt(max - min) + min;/<code>

必须当心:如果参数不大于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)算法进行随机生成。但是,我们可以提供我们的算法实现。

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

<dependency>

<groupid>org.apache.commons/<groupid>

<artifactid>commons-math3/<artifactid>

<version>3.6.1/<version>

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

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

<code>RandomDataGenerator randomDataGenerator = new RandomDataGenerator();/<code>
<code>int randomWithRandomDataGenerator = randomDataGenerator.nextInt(min, max);/<code>

2.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

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

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

<dependency>

<groupid>it.unimi.dsi/<groupid>

<artifactid>dsiutils/<artifactid>

<version>2.6.0/<version>

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

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

<code>XoRoShiRo128PlusRandom xoroRandom = new XoRoShiRo128PlusRandom();/<code>
<code>int randomWithXoRoShiRo128PlusRandom = xoroRandom.nextInt(max - min) + min;/<code>

3.最后

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

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


分享到:


相關文章: