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.
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 belowvoid 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); } });
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.
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); });
forEach() over a 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) );
forEach() over 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
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