JB Header

Java Enhanced for Loop (for-each) with Examples

Introduction Going through every element of an array or a collection is one of the most common jobs in programming. The enhanced for loop, also called the for-each loop, does it with the least code and the fewest chances for mistakes. This tutorial explains the Java enhanced for loop with examples. We will start with its syntax, and use it with arrays. We will then use it with collections such as List, Set and Map. Next we will see what the enhanced for loop cannot do - and the surprising things that happen when you try. Lastly, we will compare it with the classic for loop and the forEach() method.

(Note - This tutorial follows the for loopClick to read tutorial: Java for Loop Tutorial with Examples and while loopClick to read tutorial: Java while and do-while Loops with Examples tutorials.) Syntax of the enhanced for loop
for (Type element : arrayOrCollection) { body }
Where,
  • arrayOrCollection is an array, or any object which implements Iterable - such as a List or Set.
  • element is a variable which holds each element in turn, from the first to the last. Its Type must match the element type; var can be used too.
  • Read the colon as "in": for each element in the array.
There is no counter, no condition and no update to write - and so no way to get them wrong. Looping over arrays
The enhanced for loop with arrays
//ForEachArray.java
public class ForEachArray {
  public static void main(String[] args) {
    String[] names = {"Tom", "Harry", "Ethan", "Nancy"};
    for (String name : names) {
      System.out.println("Hello, " + name);
    }

    int[] scores = {72, 85, 90, 64, 88};
    int total = 0;
    int highest = Integer.MIN_VALUE;
    for (int score : scores) {
      total += score;
      if (score > highest) {
        highest = score;
      }
    }
    System.out.println("Total = " + total + ", highest = " + highest);

    for (char c : "Java".toCharArray()) {
      System.out.print(c + " ");
    }
    System.out.println();
  }
}
 OUTPUT of the above code
Hello, Tom
Hello, Harry
Hello, Ethan
Hello, Nancy
Total = 399, highest = 90
J a v a
Explanation of the code
  • Each pass through the loop gives the next array element to name or score, from the first position to the last.
  • Totals and maximums work just as with the classic for loop - the result variables are declared before the loop.
  • toCharArray() turns a String into a char array, so a for-each loop can go through its characters.
Looping over collections The enhanced for loop works the same way with every collection. A Map is not itself Iterable, but its keySet(), values() and entrySet() views are.
The enhanced for loop with List, Set and Map
//ForEachCollections.java
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

public class ForEachCollections {
  public static void main(String[] args) {
    List<String> cities = List.of("London", "Mumbai", "Tokyo");
    for (String city : cities) {
      System.out.println("City: " + city);
    }

    TreeSet<Integer> uniqueSorted = new TreeSet<>(List.of(5, 3, 9, 3, 1));
    for (int n : uniqueSorted) {
      System.out.print(n + " ");
    }
    System.out.println();

    Map<String, Integer> stock = new LinkedHashMap<>();
    stock.put("Pens", 120);
    stock.put("Notebooks", 45);
    stock.put("Staplers", 8);
    for (Map.Entry<String, Integer> entry : stock.entrySet()) {
      System.out.println(entry.getKey() + " -> " + entry.getValue());
    }
    for (var item : stock.keySet()) {
      System.out.print(item + "; ");
    }
    System.out.println();
  }
}
 OUTPUT of the above code
City: London
City: Mumbai
City: Tokyo
1 3 5 9
Pens -> 120
Notebooks -> 45
Staplers -> 8
Pens; Notebooks; Staplers;
Explanation of the code
  • A TreeSet keeps its elements sorted and without duplicates, and the loop visits them in that order. The Integer elements are automatically unboxed into the int variable n.
  • entrySet() gives each key-value pair of the map as a Map.Entry, which is the most efficient way to go through a map when you need both. A LinkedHashMap keeps the order in which entries were added.
  • var saves writing the element type. See the var keywordClick to read tutorial: Java var Keyword: Local Variable Type Inference.
Limitations of the enhanced for loop The enhanced for loop hides the counter and the iterator from you. That makes it simple, but it also means you cannot -
  • get the index of the current element;
  • replace elements of an array - assigning to the loop variable changes only the variable, not the array;
  • remove elements from a collection while looping - this throws a ConcurrentModificationException;
  • go backwards, skip elements, or loop over two arrays in step.
The program below tries two of these, and shows what really happens.
What the enhanced for loop cannot do
//ForEachLimits.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ForEachLimits {
  public static void main(String[] args) {
    int[] prices = {10, 20, 30};
    for (int price : prices) {
      price = price * 2;          // changes only the loop variable
    }
    System.out.println("After for-each: " + Arrays.toString(prices));

    for (int i = 0; i < prices.length; i++) {
      prices[i] = prices[i] * 2;  // the classic loop can change the array
    }
    System.out.println("After classic for: " + Arrays.toString(prices));

    List<String> names = new ArrayList<>(List.of("Tom", "Harry", "Ethan"));
    names.removeIf(name -> name.startsWith("H"));   // the safe way to remove
    System.out.println("After removeIf: " + names);

    List<String> team = new ArrayList<>(List.of("Tom", "Harry", "Ethan", "Nancy"));
    for (String name : team) {
      if (name.equals("Harry")) {
        team.remove(name);        // removing inside for-each
      }
    }
  }
}
 OUTPUT of the above code
After for-each: [10, 20, 30]
After classic for: [20, 40, 60]
After removeIf: [Tom, Ethan]
Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1096)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1050)
	at ForEachLimits.main(ForEachLimits.java:24)
Explanation of the code
  • price holds a copy of each element, so doubling it left the array unchanged. The classic for loop, which works through the index prices[i], did change it.
  • Removing an element from the list inside the for-each loop threw a ConcurrentModificationException - the hidden iterator noticed that the list had changed under it.
  • To remove elements safely, use Collection.removeIf()Click to read tutorial on Java 8 Collection.removeIf(), or an explicit Iterator and its remove() method.
for-each vs classic for vs forEach()
  • Enhanced for loop: the default choice for reading every element, in order. It is the shortest and safest form.
  • Classic for loop: use it when you need the index, want to change array elements, loop backwards or in steps, or loop over two arrays together.
  • forEach() method: since Java 8, collections have a forEach() method which takes a lambda, such as cities.forEach(city -> System.out.println(city));. It reads well for one-line actions, and is the natural partner of the Streams API. See Iterable.forEach()Click to read tutorial on Java 8 Iterable.forEach().
Using the classic loop when the index matters
//IndexWhenNeeded.java
public class IndexWhenNeeded {
  public static void main(String[] args) {
    String[] podium = {"Nancy", "Tom", "Harry"};
    for (int i = 0; i < podium.length; i++) {
      System.out.println("Place " + (i + 1) + ": " + podium[i]);
    }
    System.out.print("In reverse: ");
    for (int i = podium.length - 1; i >= 0; i--) {
      System.out.print(podium[i] + " ");
    }
    System.out.println();
  }
}
 OUTPUT of the above code
Place 1: Nancy
Place 2: Tom
Place 3: Harry
In reverse: Harry Tom Nancy
Summary In this tutorial we first looked at the syntax of the enhanced for loop, and used it to go through arrays and the characters of a string. We then used it with a List, a Set and the views of a Map. Next we saw its limitations - no index, assigning to the loop variable does not change the array, and removing from a collection inside the loop throws a ConcurrentModificationException. Lastly, we compared it with the classic for loop and the forEach() method. In the next tutorial, we will control loops from the inside with break, continue and labeled loopsClick to read tutorial: Java break, continue and Labeled Loops Explained.