为什么在 lambda 中使用 ++i 而不是 i++

why using ++i but not i++ in lambda

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

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

您可以使用限制并按照您的建议进行操作:

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

这也可以帮助:

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

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

最后一个函数(i -> ++i 在你的例子中)是确定下一个值是什么。

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

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

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

在您的 iterate() 方法中,第三个参数是一个 IntUnaryOperator。它有一个抽象方法 applyAsInt(),它接受一个 int 作为参数和 returns 一个 int。如果您将 Lambda 表达式重写为等效的匿名内部 class(您可以在此处合法使用),您将得到:

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

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