Suppose you want to count iterations of a lambda expression to know how many times it executed or iterate a list using java 8 forEach loop and lambda expression and increment a variable(declared before the loop) inside it, as shown in the below snippet

int count = 0;
list.forEach(item -> {
  count++;
});

you will get the following compiler error

Local variable x defined in an enclosing scope must be final or effectively final

A final variable is one which can be initialized only once and it is declared using final keyword.
Effectively final variable means a variable whose value is not changed after initialization. Thus, effectively final variables are also initialized only once.
Difference between final and effectively final variable is the use of final keyword only.

Below are the examples of final and effectively final variables.

// final variable
final int count = 0;

// effectively final, not changed after initialization
int unchanged = 10;

But how can you define a final variable and change its value.
This article will explain 3 different ways in which you can increment or modify a variable value inside a lambda expression or a java stream.
Method 1: Using array
Let’s say, we have a list of integers and we want to know the number of integers that are greater than 50 using a forEach loop and lambda expression.
We can not declare an integer variable and increment it inside the loop after checking the color or each ball since it will be an error.
But we can use an integer array of size 1 to hold the count as shown below.

// define a list
List<Integer> numbers = List.of(5,67,89,23,12,99,478,900);
int[] counter = new int[1];
// iterate using forEach 
numbers.forEach(num -> {
  // check if list element is greater than 50 
  if(num > 50) {
    counter[0]++;
  }
});
System.out.println("Number of integers greater than 50 = " +counter[0]);

This works since we are initializing the integer array only once but modifying the value of its element inside the loop, which is legal.
This prints

Number of integers greater than 50 = 5

Method 2: Using AtomicInteger
AtomicInteger is a wrapper around an integer value. Its actual use is in multi-threaded applications where more than one threads are acting on an integer value but it may be used in this case also.
This is the reason that it lies in java.util.concurrent package.

An AtomicInteger object can be created using its constructor supplying a default value.
It has getAndIncrement() method which gets the current value and increments it by 1 and a get() method which is used to get its value. Example,

// define a list
List<Integer> numbers = List.of(5,67,89,23,12,99,478,900);
AtomicInteger counter = new AtomicInteger();
// iterate using forEach
numbers.forEach(num -> {
   // check if list element is greater than 50 
   if(num > 50) {
      counter.getAndIncrement();
   }
});
System.out.println("Number of integers greater than 50 = "+counter.get());

Reason that we can use AtomicInteger is because it is an object that is initialized only once(making it effectively final) and we are only invoking one of its methods inside the loop which is actually modifying its value.
This prints

Number of integers greater than 50 = 5

Method 3: Using AtomicReference
Similar to AtomicInteger, java.util.concurrent.atomic.AtomicReference object can be used to count values in a forEach loop.
It has a getAndUpdate() method which takes a UnaryOperator as argument. A UnaryOperator is a functional interface and represents an operation on a single value.

// define a list
List<Integer> numbers = List.of(5,67,89,23,12,99,478,900);
AtomicReference<Integer> counter = new AtomicReference<>(0);
// iterate using forEach
numbers.forEach(num -> {
   // check if list element is greater than 50
   if(num > 50) {
      counter.getAndUpdate(value -> value + 1);
   }
});
System.out.println("Number of integers greater than 50 = "+counter.get());

Since UnaryOperator is a functional interface, it can be represented by a lambda expression which adds 1 to its argument as shown in the above example.
Current value of AtomicReference is implicitly supplied to getAndUpdate() method, which is then incremented by 1.
Output of above program is

Number of integers greater than 50 = 5

This article will be useful to most of you since increasing or modifying a variable while iterating a list using forEach loop is a very common operation.

Do not forget to hit the clap.

6
Liked the article ? Spread the word...