- Java 8:Lambda 序列化?
- Java 8 lambda 最佳实践
- Java 8 lambda 表达式 10 个示例
- Java8 lambda 表达式 10 个示例
- Java8 Lambda 表达式和流操作如何让你的代码变慢 5 倍
- Java8:Lambda 表达式增强版 Comparator 和排序
- Java 8 LongAdders:管理并发计数器的正确方式
- Java 8 Optional 类深度解析
- Java8 中的 java.util.Random 类
- Java8 中的简易并发
- Java8 学习:Lambda 表达式、Stream API 和功能性接口 — 教程、资源、书籍和实例
- Java8 并发教程:Threads 和 Executors
- Java 8 新特性之旅:使用 Stream API 处理集合
- Java 8 新特性探究(一)通往 lambda 之路_语法篇
- Java 8 新特性探究(六)泛型的目标类型推断
- Java 8 新特性探究(七)深入解析日期和时间-JSR310
- Java 8 新特性探究(八)精简的 JRE 详解
- Java 8 新特性探究(九)跟 OOM:Permgen 说再见吧
- 总结
- Java 8 新特性探究(十)StampedLock 将是解决同步问题的新宠
- Java 8 新特性探究(十一)Base64 详解
- Java 8 新特性探究(十二)Nashorn :新犀牛
- Java 8 新特性终极指南
- Java 8 新的时间日期库的 20 个使用示例
- Java8 日期时间(Date Time)API 指南
- Java8 本地缓存
- Java 8 的 default 方法能做什么?不能做什么?
- Java 8 的 6 个问题
- Java 8 简明教程
- Java8 集合中的 Lambda 表达式
- Java SE 8 新的时间和日期 API
- 在 Java 8 下更好地利用枚举
- 在 Java 8 中避免 Null 检查
- 鲜为人知的 Java8 特性:泛化目标类型推断
Java8 中的 java.util.Random 类
在 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论