Java lambda-for循环计数器不是有效的final

Java lambda-for循环计数器不是有效的final,java,for-loop,lambda,java-8,Java,For Loop,Lambda,Java 8,鉴于lambda在for循环中的这种情况,我希望计数器I实际上是最终的 编译器抱怨我不是有效的final,所以我不得不使用i2 for (int i = 0; i < x.getBooks().size(); i++){ //The compiler needs i to be effectively final. int i2 = i; List<Book> books = bookstore.stream() .fi

鉴于lambda在for循环中的这种情况,我希望计数器I实际上是最终的

编译器抱怨我不是有效的final,所以我不得不使用i2

for (int i = 0; i < x.getBooks().size(); i++){
   //The compiler needs i to be effectively final.
   int i2 = i;
   List<Book> books = bookstore.stream()
                    .filter(c -> c.getAuthors().get(i2).equals("xxx"))
                    .collect(Collectors.toList());
}
for(inti=0;ic.getAuthors().get(i2).equals(“xxx”))
.collect(Collectors.toList());
}

所以问题是为什么我在for循环的范围内不是有效的final,这是最简单的解决方法。

您必须记住,for循环实际上相当于:

int i=0;
while(i < x.getBooks().size()){
  //execute your block
  i++;
}
inti=0;
而(i
所以您可以看到,
i
只声明了一次,因此没有有效地更新为final


有点不清楚
x.getBooks()
Book.getAuthors()
之间的关系,但显然它们的大小相同?如果没有更好的理解,我想我无法向你展示更好的方法。但这也可能表明您的设计很差。

TLDR:
i
不是
final
,因为它在
for
循环的每次迭代中都会被修改(
i++


为什么我在for循环的范围内不是有效的final

循环的
语法为

for (initialization; termination; increment) {
    statement(s)
}
增量表达式在循环的每次迭代后调用。在您的例子中,增量是
i++
,因此每次迭代后都会修改
i

您可以通过声明
i
final来确认这一点:

for (final int i = 0; i < x.getBooks().size(); i++) {
}

这是最简单的解决方法吗

对于
循环的
:是

但是您可以使用所示的
while
循环或
foreach

int i = 0;
for (Book book: x.getBooks()) {
    int i2 = i;
    ...  
    i++;
}

正如其他答案所提到的,
实际上是final
意味着一个变量只能赋值一次,不会被重新赋值。在for循环中,情况并非如此
final
有效地存在,因为否则开发人员必须显式地将变量标记为
final
才能在lambda中使用它

但是,我回答的原因是一个解决方案,即编写代码时不复制
i

IntStream.range (0, x.getBooks().size()).forEach (i -> {
    List<Book> books = bookstore.stream()
                                .filter(c -> c.getAuthors().get(i).equals("xxx"))
                                .collect(Collectors.toList());
});
IntStream.range(0,x.getBooks().size()).forEach(i->{
List books=bookstore.stream()
.filter(c->c.getAuthors().get(i).equals(“xxx”))
.collect(Collectors.toList());
});
来自

基本for语句(§14.14.1)的
ForInit
部分中声明的局部变量的范围包括以下所有内容:

  • 它自己的初始值设定项
  • for语句的
    ForInit
    部分右侧的任何其他声明符
  • for语句的
    表达式和
    ForUpdate
    部分
  • 所载声明
大约

局部变量或方法、构造函数、lambda或异常 如果参数未声明为final,但 从不作为赋值运算符的左操作数出现 (§15.26)或作为前缀或后缀增量的操作数,或 减量运算符

i
变量作为后缀增量运算符的操作数出现

i++

因此,它不是有效的最终版本,不能被lambda捕获。

您在哪里使用
i
i2
?有效的最终版本?我不知道那是什么意思。你的代码甚至没有在lambda中使用
i
,对现在编辑的输入错误表示歉意。这实际上意味着实际的示例有些人为制造,所以不要太担心。主要问题与for循环中计数器的范围有关。@Dan好的,那么也许我回答的第一部分就足够了?在您的
foreach
示例中,
i
的语义已经更改。第一次循环时是0。现在第一次是1。此外,同样的问题也存在,它不是有效的最终版本,因此仍然需要
i2
i++