Java forEach method was introduced in Iterable interface in Java 8. Java 8 forEach method is another way that we can use to traverse through a collection.
Java forEach
Below code snippet shows the default implementation of java forEach method in Iterable interface. Read java 8 interface changes to learn more about default interface methods.
1 2 3 4 5 6 7 8 |
default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } |
Java forEach method performs the given action for each element of the Iterable until all elements have been processed or exception is thrown.
Java 8 forEach List Example
Before java 8, We could iterate over a list by using for loop or iterator.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
List<String> list = getList(); //prior to java 8 //using enhanced for loop for(String s : list){ System.out.println(s); } //using iterator Iterator<String> it = list.iterator(); while(it.hasNext()){ System.out.println(it.next()); } |
Now same thing can be performed using java forEach method as shown below.
1 2 3 4 5 6 7 8 9 10 11 |
// Create Consumer instance Consumer<String> action = new Consumer<String>(){ @Override public void accept(String t) { System.out.println(t); } }; //java 8 forEach list.forEach(action); |
Since Consumer is a functional interface, we can use lambda expression and write above code in one line as;
1 2 3 |
list.forEach(k -> {System.out.println(k);}); |
Java 8 forEach Map Example
Prior to java 8, we iterate over Map elements like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Map<Integer,String> map = getMap(); //iteration prior to java 8 Set<Integer> keySet = map.keySet(); //using enhanced for loop for (Integer i : keySet){ System.out.println(map.get(i)); } //using iterator Iterator<Integer> it = keySet.iterator(); while(it.hasNext()){ System.out.println(map.get(it.next())); } |
Since Map doesn’t extend Iterable, forEach method is added into Map interface in java 8 and below shows the default implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
default void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); for (Map.Entry<K, V> entry : entrySet()) { K k; V v; try { k = entry.getKey(); v = entry.getValue(); } catch(IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } action.accept(k, v); } } |
Let’s look at a simple example how we can use java 8 forEach with Map.
1 2 3 4 5 6 7 8 9 10 |
BiConsumer<Integer,String> action = new BiConsumer<Integer, String>(){ @Override public void accept(Integer t, String u) { System.out.println(u); } }; //java 8 forEach with Map map.forEach(action); |
Same code can be written using lambda expressions as below.
1 2 3 |
map.forEach((k,v) -> {System.out.println(v);}); |
Java forEach Benefits
I don’t see too much benefit of forEach loop except when you are using it with parallel stream. A new method was added in Collection interface to get the parallel stream.
1 2 3 4 5 |
default Stream<E> parallelStream() { return StreamSupport.stream(spliterator(), true); } |
So if we have to iterate over a collection and we are not bothered about sequential iteration, then we can use parallel stream with forEach loop as shown below.
1 2 3 4 |
//parallel operation using stream list.parallelStream().forEach(action); |
That’s all for Java forEach method. I hope you will find some use case for java 8 forEach method in parallel processing.