为什么Stream.limit在此代码段中没有按预期工作?

时间:2015-12-09 07:25:54

标签: java java-8 java-stream

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来电永远不会回来。在limit之前设置filter会产生预期结果。为什么?

4 个答案:

答案 0 :(得分:34)

由于只有4个元素通过过滤器,limit(10)永远不会达到10个元素,因此Stream管道不断生成新元素并将它们提供给过滤器,尝试达到通过过滤器的10个元素,但是因为只有前4个元素通过过滤器,所以处理永远不会结束(至少在i溢出之前)。

Stream管道不够智能,不知道没有更多元素可以通过过滤器,因此它会继续处理新元素。

答案 1 :(得分:25)

翻转limitfilter子句会有不同的行为。

如果先放置limit,则流将首先生成10个整数[1..10],然后过滤它们,只留下小于5的整数。

在原始排序中,首先应用filter,生成并过滤整数,直到达到10个元素。这不是一个无限的运算符,因为供应商中的i最终会溢出,但是需要一段时间,特别是在慢速计算机上,才能达到MAX_INT

答案 2 :(得分:18)

如果你想要停止 ,如果达到了数字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());

答案 3 :(得分:9)

在供应商溢出并开始产生负数后,它将完成。结果列表将包含:

[1, 2, 3, 4, -2147483648, -2147483647, -2147483646, -2147483645, -2147483644, -2147483643]

其原因在于其他答案。在我的i7机器上完成需要40秒。