Java 8 forEach
In this article, we will understand forEach loop added in java 8 to iterate over Collections such as a list, set or map or over java streams with example programs.

Overview
forEach() is a method introduced in java 8 in java.lang.Iterable interface and can be used to iterate over a collection.

forEach() is a default interface method which takes a java.util.function.Consumer as argument.
Syntax of forEach() method is given below

void forEach(Consumer<? super T> action) { }

Using forEach()
forEach() accepts an argument of type Consumer. It is a functional interface and hence, contains a single method accept(), which takes a single argument and returns no value.
Signature of accept() method is

void accept(T t);

forEach() method is invoked on a collection and is invoked automatically for each element of the collection.
Thus, it can be said that for every element, accept() method of Consumer interface is invoked with a collection element as argument value.
We need to define implementation of accept() method as per our requirement.

There are 3 ways to implement accept() method.
1. Implement Consumer interface in a class
Create a class implmenting Consumer interface and hence, its accept() method as shown below.

public class ConsumerImpl implements Consumer<String> {
   @Override
   public void accept(String s) {
      System.out.println(s);
   }
}

Then, supply the object of this class to forEach() as below

list.forEach(new ConsumerImpl());

2. Anonymous Consumer Implementation
Instead of creating a separate class for implementing Consumer interface, define implementation of accept() method inline as an anonymous inner class as shown below

list.forEach(new Consumer<String>(){
   public void accept(String t) {
      System.out.println(t);
   }
});
Consumer is a generic interface. Type of Consumer and the type of argument of accept() method must be same, which is, String in above example.

3. As a Lambda expression
Since Consumer is a Functional interface, its accept() method can be implemented as a Lambda expression as shown below

list.forEach((t) -> {
   System.out.println(t);
});

In all examples of forEach(), we will be using lambda expression, since it makes the code concise and clean.

forEach() over list
A list can be iterated using forEach() as shown in the example below.

// define a list of integers
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// iterate with forEach
numbers.forEach(num -> {
      System.out.println(num);
});

Java forEach ArrayList of objects
More often, we need to iterate over an arraylist of custom or user defined objects.
With forEach(), this can be done as in below example

class Employee {
  private int id;
  private String name;

  public Employee(int id, String name) {
    this.id = id;
    this.name = name;
  }

  // getter and setter methods
}

public class ArrayListIterator {
  public static void main(String ... a) {
    // create a list
    List<Employee> emp = new ArrayList<>();
    // create employee objects
    Employee one = new Employee(1, "A");
    Employee two = new Employee(2, "B");
    // add objects to list
    emp.add(one);
    emp.add(two);
    // iterate list of objects with forEach
    emp.forEach(e -> {
      System.out.println("Employee name: " + e.getName());
    });
}

Here, we have an arraylist of objects of custom class, Employee, which is iterated using a forEach loop.

Java forEach stream
Java 8 streams can also be iterated using forEach() method. Example program is given below.

// define a list of integers
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// iterate over a stream
numbers.stream().forEach(
   num -> System.out.println(num)
);

Java forEach Map
forEach() method can be used to loop over a Map as shown below. java.util.Map interface defines a different forEach() method which takes a BiConsumer as argument.
java.util.function.BiConsumer is a Functional interface with a single method accept() that takes two arguments as shown below.

void accept(T t, U u);

When forEach() is invoked on a map, it internally invokes accept() method with key and value of current map element passed as arguments. Example,

Map<Integer, String> map = new HashMap<>();
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");
map.forEach((k,v) -> {
    System.out.println("Key: " + k + ", Value: " + v);
});

This prints

Key: 1, Value: A
Key: 2, Value: B
Key: 3, Value: C

Java array forEach
To use forEach over a java array, we need to get a stream over an array using Arrays.stream() method as shown below.

int[] nums = {1, 2, 3, 4, 5};
Arrays.stream(nums).forEach(num-> System.out.print(num));

forEach cannot be directly used over an array, since forEach is defined in Iterable interface and arrays are no way related to this interface.
Java forEach index
Java forEach has no mechanism to access loop counter or element index directly as in traditional for loop, since you don’t need it to access elements.
But, in case, it is required to iterate a list with index, then you can initialize an integer to 0 before the loop and increment it inside the loop as shown below

// define a list of integers 
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 
// initialize index variable
int counter = 0;
numbers.forEach( num -> {
  System.out.println(num); 
  counter++;
});

forEach() vs for-each
for-each, also known as enhanced for loop is compared with forEach() but both of these have differences. Following are the important differences summarized below.
1. forEach() is a method while for-each is a loop.
2. forEach() is introduced in java 1.8 while for-each loop was added in java 1.5.
3. You can supply lambda expresssion to forEach() but for-each loop doesn’t support lambda expressions.
4. Lambda expression used in forEach() loop cannot use non-final variables. Thus, below code is not allowed

int sum = 0;
list.forEach( x -> {
 // error: sum is not final
 sum += x;
});

While it is allowed in for-each loop.
5. You cannot use break statement in a lambda expression given in forEach() while it can be used in a for-each loop.

Hope the article was useful.

0
Liked the article ? Spread the word...