Java 8 variable should be final or effectively final issue

1.7k views Asked by At

I am using Java 8 stream Iteration with a variable that should be used in other classes also. So I have used the below code.

AtomicBoolean bool = new AtomicBoolean(true);
public void testBool(){
list.stream().forEach(c->{ 
      if( c.getName() != null){
    bool.set(true);
    }
});

}

public void test(){
  if(bool.get()){
    System.out.println("value is there");
  }
}

But I heard like using the Atomic Object will be a performance hit sometimes. Is there any alternate approach to use the variables outside the forEach block with Java 8 usage? Without this am getting the error as a variable should be a final or effectively final error.

Please help me to resolve this issue.

Thanks in advance.

2

There are 2 answers

2
Omeri On BEST ANSWER

You could avoid the problem by using the lambda expression to return true or false if there are any names that are not null, and assign the result to your boolean.

Something like this:

boolean hasAnyWithNames = list.stream().anyMatch(c -> c.getName() != null);

The choice bool is not a good one for variable name by the way.

Edit:

  • Replaced Boolean with base type per comment.
  • Used anyMatch() instead of filter() count per comment Thanks
1
CausingUnderflowsEverywhere On

The effectively final restriction only applies to local variables.
Since you are setting an instance field, you can simply use: boolean bool = true; and set it from within the lambda.

If you need to use a local variable, add the final modifier to the declaration.

Regarding the overhead of using AtomicBoolean, keep in mind that streams also have overhead and if you're only using them for iteration you're better off using a for loop instead:

boolean bool = true;

    public void testBool(){
        for (var c : list) {
            if (c.getName() != null) {
                bool = true;
                break;
            }
        }
    }

Lastly, as @Neela mentioned in a comment, a more efficient use of streams would be with the following code*:

boolean bool = list.stream().anyMatch(c -> c.getName() != null);

*Note, the original code has an error that results in bool always being true and this is avoided by not presetting true and directly putting the result of anyMatch.