Ann*_*ein 16 java random java-stream
我已经创建了一个randomIntStream:
final static PrimitiveIterator.OfInt startValue = new Random().ints(0, 60).iterator();
Run Code Online (Sandbox Code Playgroud)
文档说这个流实际上是无穷无尽的.
我想了解背景中发生了什么.
ints(0,60)
正在生成无限的整数流.如果这是无限的,为什么我的机器没有泄漏任何内存?
我想知道,实际上生成了多少个数字,以及这个实现是否会在流仍然结束时导致错误?或者这个流会不断地在飞行中充满新的整数,它真的永远不会结束吗?
如果我已经提出这个问题,那么现在生成随机数的最佳做法是什么?
Kay*_*man 17
流是无限¹所以您可以生成任意数量的整数而不会耗尽.这并不意味着当你不要求它时它会继续生成它们.
实际生成了多少个数字取决于您编写的代码.每次从迭代器中检索值时,都会生成一个值.没有在后台生成,因此没有使用"额外"内存.
¹就你的一生而言,请参阅Eran的回答
Era*_*ran 12
确切地说,
IntStream java.util.Random.ints(int randomNumberOrigin, int randomNumberBound)
收益:
一个有效无限的伪随机int值流,每个值符合给定的原点(包括)和绑定(不包括).
这并不意味着无限.查看Javadoc,您将看到一个实现说明,指出它实际上限制了返回IntStream
的Long.MAX_VALUE
元素:
实施说明:
实现此方法等同于int(Long.MAX_VALUE,randomNumberOrigin,randomNumberBound).
当然Long.MAX_VALUE
是一个非常大的数字,因此返回IntStream
可以被视为"有效"无限制.例如,如果int
每秒消耗该流的1000000 秒,则大约需要292471年才能耗尽元素.
也就是说,正如其他答案所提到的那样,IntStream
只产生其消费者所需的数量(即消耗int
s 的终端操作).
没有存储。流不是存储元素的数据结构;相反,它通过计算操作的管道传送来自数据结构、数组、生成器函数或 I/O 通道等源的元素。
相反,每次流前进时,每个流元素都被一一计算。在您的示例中,int
当您调用startValue.nextInt()
.
因此,当我们执行 eg 时new Random().ints(0,60)
,流实际上是无限的这一事实不是问题,因为int
在我们执行一些遍历流的操作之前,实际上不会计算随机s。一旦我们遍历了流,int
s 只会在我们请求它们时计算。
这是一个使用Stream.generate
(也是一个无限流)的小例子,它显示了这个操作顺序:
Stream.generate(() -> {
System.out.println("generating...");
return "hello!";
})
.limit(3)
.forEach(elem -> {
System.out.println(elem);
});
Run Code Online (Sandbox Code Playgroud)
该代码的输出是:
generating...
hello!
generating...
hello!
generating...
hello!
Run Code Online (Sandbox Code Playgroud)
请注意,我们的生成器供应商在每次调用forEach
消费者之前都会被调用一次,以后不会再调用了。如果我们不使用limit(3)
,程序可以永远运行,但不会耗尽内存。
如果我们这样做new Random().ints(0,60).forEach(...)
,它会以同样的方式工作。该流将random.nextInt(60)
在每次调用forEach
消费者之前执行一次。元素不会在任何地方累积,除非我们使用了一些需要它的操作,例如distinct()
或 收集器而不是forEach
。
Stream.Builder
需要一个数据结构来放置它们的元素。 归档时间: |
|
查看次数: |
1552 次 |
最近记录: |