为什么在lambda

时间:2017-08-02 01:16:27

标签: lambda java-9

我碰巧知道,在下面的表达式中,使用i++将导致无限流,i将始终为0.我感到困惑是因为我认为i++返回值没有使用,即便如此,它不应该在之后中断i增量。

IntStream.iterate(0, i-> i<10, i-> ++i).forEach(....)

3 个答案:

答案 0 :(得分:4)

通过检查Java 9的IntStreamhttp://download.java.net/java/jdk9/docs/api/java/util/stream/IntStream.html#iterate-int-java.util.function.IntPredicate-java.util.function.IntUnaryOperator-

的API

最后一项功能(在您的情况下为i -> ++i)是确定下一个值是什么。

如果你放i->i++,假设它是一个后缀增量运算符,i++在递增之前计算为i。这意味着它总是返回相同的值(在您的情况下为种子0)。因此,它就像你放i -> i一样。请注意,Java中的参数是按值传递的。因此,lambda中的增量不会影响调用者。

因此,hasNext谓词(第二个参数,在您的情况下为i->i<10)始终计算为true,因此为您提供无限的全零流。

答案 1 :(得分:1)

您可以使用限制并按照您的建议行事:

IntStream.iterate(0, i -> i++).limit(10).forEach(....)

这也有帮助:

Java Incremental operator query (++i and i++)

答案 2 :(得分:0)

请记住,lambda表达式是一种表示功能接口(只有一个抽象方法的接口)作为匿名函数的方法。

在iterate()方法中,第三个参数是IntUnaryOperator。这有一个抽象方法applyAsInt(),它接受一个int作为参数并返回一个int。如果你将Lambda表达式重写为等效的匿名内部类(你可以在这里合理地使用它),你会得到:

IntStream.iterate(0, i -> i < 10, new IntUnaryOperator() {
  @Override
  public int applyAsInt(int i) {
    return i++;
  }
})
.forEach(System.out::println);

在这种情况下,很明显你在i递增之前返回i的值(后缀运算符)。 i的初始值为零,因此您将获得无限的零流。如果更改applyAsInt()方法以使用前缀运算符++ i,则i的值将在返回之前递增,从而为您提供所需的结果1,2 ... 9