[英]Why doesn't Stream.limit work as expected in this snippet?
List<Integer> integer = Stream.generate(new Supplier<Integer>() {
int i = 0 ;
@Override
public Integer get() {
return ++i;
}
}).filter(j -> j < 5)
.limit(10) // Note the call to limit here
.collect(Collectors.toList());
与我的预期相反, collect
调用永不返回。 在filter
产生预期结果之前设置limit
。 为什么?
由于只有4个元素通过过滤器,所以limit(10)
永远不会达到10个元素,因此Stream管道会不断生成新元素并将其馈送到过滤器,以尝试达到10个通过过滤器的元素,但是由于只有第一个4个元素通过过滤器,处理过程永不结束(至少直到i
溢出)。
Stream管道不够智能,无法知道没有更多元素可以通过过滤器,因此它会继续处理新元素。
limit
和filter
子句具有不同的行为。
如果将limit
放在首位,则流将首先生成10个整数[1..10],然后对其进行过滤,仅保留小于5的那些整数。
在原始顺序中,首先应用filter
,然后生成并过滤整数,直到达到10个元素。 这不是一个无限运算符,因为供应商中的i
最终会溢出,但是要花一些时间(尤其是在速度较慢的计算机上)才能达到MAX_INT
。
如果您想在达到5或收集10个元素时停止,则Java-9中添加了Stream.takeWhile()
方法:
List<Integer> integer = Stream.generate(new Supplier<Integer>() {
int i = 0 ;
@Override
public Integer get() {
return ++i;
}
}).takeWhile(j -> j < 5).limit(10).collect(Collectors.toList());
在供应商溢出并开始生成负数之后,它将完成。 结果列表将包含:
[1, 2, 3, 4, -2147483648, -2147483647, -2147483646, -2147483645, -2147483644, -2147483643]
原因是在其他答案中。 在我的i7机器上,花了40秒完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.