How does the "forEach" loop work in Java?
Tags: java, programming, tutorial
Published: 2021-10-24 16:54:37

Java 8 has introduced many features, and the forEach() method is one of them. 

In short, it's a way to iterate over a Collection (for example, a map, a set or a list) or a  [Stream](https://techwithmaddy.com/java-8-streams). 

The forEach() takes only one parameter, which is a  [functional interface](https://techwithmaddy.com/java-8-functional-interfaces) . This means that you can use a  [lambda expression](https://techwithmaddy.com/java-8-lambda-expression) as an argument. 

Let's see some examples to understand how the forEach() works on Collections and Streams.

**FOREACH() ON A LIST**

```
import java.util.ArrayList;
import java.util.List;

public class Fruit {

    public static void main(String[] args) {

        List<String> listOfFruits = new ArrayList<>();
        listOfFruits.add("apple");
        listOfFruits.add("pear");
        listOfFruits.add("banana");
        listOfFruits.add("mango");

        //using a lambda expression
        listOfFruits.forEach(x -> System.out.println(x));

        //using a method reference
        listOfFruits.forEach(System.out::println);

    }
}

```
The outcome in both cases is:
```
apple
pear
banana
mango
```
In the code snippet above, we are:
- Creating a List called _listOfFruits_.
- Adding items to the list.
- Looping through the items and printing them using a lambda expression or a method reference.

**FOREACH() ON A MAP**

```
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Fruit {

    public static void main(String[] args) {

        Map<Integer, String> mapOfFruits = new HashMap<>();
        mapOfFruits.put(1, "apple");
        mapOfFruits.put(2, "pear");
        mapOfFruits.put(3, "banana");
        mapOfFruits.put(4, "mango");

        mapOfFruits.forEach((x, y) -> System.out.println(x + " " + y));

    }
}

```

The outcome is:
```
1 apple
2 pear
3 banana
4 mango
```
In the code snippet above, we are:
- Creating a _mapOfFruits_ with Integer as the key and String as the value.
- Populating the map with different fruits. For example, key 1 is linked to apple. And so on.
- Looping through the items and printing their keys and values using a lambda expression.

**FOREACH() ON A SET**

```
import java.util.HashSet;
import java.util.Set;

public class Fruit {

    public static void main(String[] args) {

        Set<String> setOfFruits = new HashSet<>();

        setOfFruits.add("apple");
        setOfFruits.add("pear");
        setOfFruits.add("banana");
        setOfFruits.add("mango");
        
        setOfFruits.forEach(x -> System.out.println(x));

    }
}
```
The outcome is:
```
banana
apple
pear
mango
```
In the code snippet above, we are:
- Creating a _setOfFruits_.
- Adding fruits to the set.
- Looping through the items and printing them using a lambda expression.

**NOTE**: a Set doesn't guarantee any order. Also, it doesn't accept duplicates. If you try to add another "mango", you won't get any compilation error, but it won't print out the second "mango".

**FOREACH() ON A STREAM**

```
import java.util.ArrayList;
import java.util.List;

public class Fruit {

    public static void main(String[] args) {

        List<String> listOfFruits = new ArrayList<>();
        listOfFruits.add("apple");
        listOfFruits.add("pear");
        listOfFruits.add("banana");
        listOfFruits.add("mango");

        listOfFruits.stream()
                .forEach(x -> System.out.println(x));
    }
}
```
**FOREACH() TO PRINT A FILTERED LIST OF ITEMS**

```
import java.util.ArrayList;
import java.util.List;

public class Fruit {

    public static void main(String[] args) {

        List<String> listOfFruits = new ArrayList<>();
        listOfFruits.add("apple");
        listOfFruits.add("pear");
        listOfFruits.add("banana");
        listOfFruits.add("mango");

        listOfFruits.stream()
                .filter(x -> x.length() == 5)
                .forEach(x -> System.out.println(x));
    }
}

```
The outcome is:
```
apple
mango
```
In the code snippet above, we are:
- Creating a _listOfFruits_.
- Adding fruits to the list.
- Using the Stream API to filter out those fruits whose length is equal to 5.
- Looping through the filtered list and printing the items using a lambda expression.

**FOREACH() vs FOREACHORDERED()**

If you want to ensure that the items are printed in order, you can use the **forEachOrdered()** method. This method is a **terminal operator**. The forEach() always goes at the end of a Stream because there is nothing to return after its execution. The same goes for the forEachOrdered() method. 

Let's look at an example to understand this better:

```
import java.util.Arrays;
import java.util.List;

public class Fruit {

    public static void main(String[] args) {

        List<String> listOfFruits = Arrays.asList("apple", "mango", "pear", "banana");

        //using forEach()
        listOfFruits.stream().parallel().forEach(System.out::println);
        System.out.println("-------------------");
        // using forEachOrdered()
        listOfFruits.stream().parallel().forEachOrdered(System.out::println);

    }
}

```

The outcome is:
```
pear
banana
apple
mango
-------------------
apple
mango
pear
banana
```

**WHAT IS THE DIFFERENCE BETWEEN A FOREACH() AND A FOREACHORDERED()?**

When using parallelism (in short, when things run simultaneously) on a forEach(), the order of items is not guaranteed. The forEachOrdered() is a way to explicitly say that you want to maintain the order of encounter, and indeed the items are printed that way.

**WHAT ARE THE ADVANTAGES OF USING A FOREACH() LOOP?**

✅ **The code is more readable**: if you compare the forEach() with a regular for loop, the forEach() is more readable and concise because you don't have to declare the initialization, condition and the increment or decrement.

✅ **It's bug-free**.

I hope you've found this article useful! Until next time. 😊