Java lambda - for loop counter is not effectively final

for-loop, java, java-8, lambda

Solution

TLDR: `i` is not `final` because it is modified (`i++`) at each iteration of the `for` loop.

why i is not effectively final inside the scope of the for loop ?

The `for` loop syntax is

for (initialization; termination; increment) {
    statement(s)
}

The increment expression is invoked after each iteration through the loop. In your case, increment is `i++` so `i` is modified after each iteration.

You could confirm this by declaring `i` final:

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

you will get this compilation error:

The final local variable i cannot be assigned.
It must be blank and not using a compound  assignment

is this the simplest workaround ?

In the case of a `for` loop: yes.

But you could use a `while` loop as shown by @dkatzel or a `foreach`:

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

Problem

Given this situation where a lambda is inside a for loop I would expect the counter i to be effectively final. The compiler complains that i is not effectively final so I had to use 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()); } ``` So the question is why i is not effectively final inside the scope of the for loop and is this the simplest workaround.

Original source

Related problems