我通过以下方式创建了randomIntStream:
final static PrimitiveIterator.OfInt startValue = new Random().ints(0, 60).iterator();
文档说,这个流实际上是无止境的。
我想了解背景发生的事情。
ints(0,60)
正在生成无限个整数流。如果这是无限的,为什么我的机器没有泄漏任何内存?
我想知道,实际上实际生成了多少个数字,并且这种实现是否会在流仍然结束的地方导致错误?还是该流会不断不断地充满新的整数,因此它真的永远不会结束吗?
如果我已经问过这个问题,那么现在最佳实践权现在是什么?
答案 0 :(得分:17)
流是无限的¹,因此您可以生成任意数量的整数,而不会用完。这并不意味着它在您不要求任何内容时就不断生成它们。
实际生成多少个数字取决于您编写的代码。每次您从迭代器检索值时,都会生成一个值。不会在后台生成任何内容,因此不会使用“额外”内存。
¹就您的一生而言,请参阅伊兰的答案
答案 1 :(得分:12)
确切地说,
IntStream java.util.Random.ints(int randomNumberOrigin, int randomNumberBound)
返回:
有效无限个伪随机整数值流,每个值均符合给定的原点(包含)和边界(不含)。
这并不意味着无限。查看Javadoc,您会看到一个实施说明,指出它实际上将返回的IntStream
限制为Long.MAX_VALUE
个元素:
实施说明:
此方法的实现等效于ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)。
当然Long.MAX_VALUE
是一个非常大的数字,因此返回的IntStream
可以被视为“有效”而没有限制。例如,如果您每秒消耗该流中的1000000 int
秒,则用完约292471年的时间将元素用完。
正如其他答案所述,IntStream
仅产生其使用者所需的数字(即消耗int
的终端操作)。
答案 2 :(得分:4)
正如@Kayaman在回答中所说。流是无限的,可以永久生成数字 。重点在于 can 一词。仅当您确实要求数字时,它才会生成数字。它不仅会生成X数量的数字,然后将它们存储在某个位置(除非您告诉它这样做)。
因此,如果要生成 n (其中n是整数)个随机数。您可以在ints(0, 60)
返回的流上调用ints(n, 0, 60)
,Random#ints()
的重载:
new Random().ints(n, 0, 60)
以上仍然不会生成 n 个随机数,因为它是IntStream
,它是延迟执行的。因此,当不使用终端操作(例如collect()
或forEach()
)时,什么也没有发生。
答案 3 :(得分:4)
Streams do not (in general1) store all of their elements in any kind of a data structure:
没有存储空间。流不是存储元素的数据结构。相反,它通过一系列计算操作从数据结构,数组,生成器功能或I / O通道等源中传递元素。
相反,每当流前进时,就对流元素进行一对一计算。在您的示例中,调用int
时实际上将计算每个随机startValue.nextInt()
。
例如,当我们这样做时new Random().ints(0,60)
,实际上是无限的流不是问题,因为在执行遍历流的操作之前,实际上不会计算出随机的int
。一旦遍历流,int
仅在我们请求时计算。
这是一个使用Stream.generate
(也是一个无限流)的小示例,它显示了以下操作顺序:
Stream.generate(() -> {
System.out.println("generating...");
return "hello!";
})
.limit(3)
.forEach(elem -> {
System.out.println(elem);
});
该代码的输出为:
generating...
hello!
generating...
hello!
generating...
hello!
请注意,我们的发电机供应商在forEach
消费者每次致电之前都被致电过一次,没有更多了。如果我们不使用limit(3)
,则该程序可以永久运行,但不会耗尽内存。
如果我们执行了new Random().ints(0,60).forEach(...)
,它将以相同的方式工作。在每次调用random.nextInt(60)
使用者之前,该流都会执行一次forEach
。除非我们使用某些需要操作的操作,例如distinct()
或收集器而不是forEach
,否则元素将不会在任何地方累积。
Stream.Builder
创建的流)将需要一种数据结构来放入其元素。答案 4 :(得分:2)
创建生成器不会生成任何数字。从概念上讲,此生成器将不断生成新的数字。当询问时,它不会在任何时候不返回下一个值。