Java 随机数流,用户希望在指定范围内生成整型、长整型或双精度随机数流,使用 java.util.Random
类定义的 ints
、longs
与 doubles
方法。如果仅需要生成一个双精度随机数,则不妨采用静态 Math.random
方法,它返回一个位于 0.0 和 1.0 之间的双精度值。
Java 随机数流 问题描述
用户希望在指定范围内生成整型、长整型或双精度随机数流。
Java 随机数流 解决方案
使用 java.util.Random
类定义的 ints
、longs
与 doubles
方法。
Java 随机数流 具体实例
如果仅需要生成一个双精度随机数,则不妨采用静态 Math.random
方法,它返回一个位于 0.0 和 1.0 之间的双精度值 3。这个过程相当于将 java.util.Random
类实例化并调用 nextDouble
方法。
3根据 Javadoc 的描述,返回值在指定范围内是“伪随机且(近似)均匀分布的”(pseudorandomly with (approximately) uniform distribution)。这表明,在讨论随机数生成器时必须做好两手准备。
Random
类定义了一个用于指定随机种子的构造函数。指定的种子相同,生成的随机数序列也相同,这在测试中相当有用。
如果需要生成随机数顺序流,可以使用 Random
类引入的 ints
、longs
与 doubles
方法,三者的签名如下(未显示相应的重载形式):
IntStream ints()
LongStream longs()
DoubleStream doubles()
借由三种方法的重载形式,我们可以指定结果流的大小以及生成数的最小值和最大值。以 doubles
方法为例:
DoubleStream doubles(long streamSize, double randomNumberOrigin,
double randomNumberBound)
返回流生成给定数量(streamSize
)的双精度伪随机数,每个数大于或等于 randomNumberOrigin
,且严格小于 randomNumberBound
。
如果未指定 streamSize
,方法将返回一个所谓的“有效无限流”(effectively unlimited stream)4。
4可以将流视为无限,但从技术上讲它是有限的。这里的“无限”相当于 Long.MAX_VALUE
。——译者注
如果不指定最小值或最大值,对于 doubles
方法,最小值默认为 0,最大值默认为 1;对于 ints
方法,最小值和最大值默认为整型数据的完整范围;对于 longs
方法,最小值和最大值默认为长整型数据的(有效)完整范围。就上述三种情况而言,结果相当于重复调用 nextDouble
、nextInt
与 nextLong
。
示例代码如例 5-7 所示。
例 5-7 生成随机数流
Random r = new Random();
r.ints(5) ➊
.sorted()
.forEach(System.out::println);
r.doubles(5, 0, 0.5) ➋
.sorted()
.forEach(System.out::println);
List<Long> longs = r.longs(5)
.boxed() ➌
.collect(Collectors.toList());
System.out.println(longs);
List<Integer> listOfInts = r.ints(5, 10, 20)
.collect(LinkedList::new, LinkedList::add, LinkedList::addAll); ➍
System.out.println(listOfInts);
❶ 五个随机整数
❷ 五个位于 0(包括)和 0.5(不包括)之间的双精度随机数
❸ 将 long
装箱为 Long
以便收集
❹ 使用 collect
而非调用 boxed
如果在创建基本数据类型集合时遇到问题,后两个代码段给出了解决方案。我们无法对基本数据类型集合调用 collect(Collectors.toList())
,相关讨论请参见范例装箱流。该范例建议,既可以通过 boxed
方法将 long
型数据转换为 Long
的实例,也可以使用 collect
方法的三参数形式并自行指定 Supplier
、累加器与组合器。
值得注意的是,SecureRandom
属于 Random
的子类,它提供一个加密的强随机数生成器(cryptographically strong random number generator)。Random
类定义的 ints
、longs
与 doubles
方法(以及它们的重载形式)同样适用于 SecureRandom
类,区别仅在于所用的生成器不同。