Skip to content
Java control flow 5 min read

for-each Loop

The for-each loop (also called the enhanced for loop) lets you walk through every element of an array or collection without managing an index or an iterator yourself. Your code becomes shorter, more readable, and less prone to off-by-one bugs.

Syntax

for (Type element : arrayOrCollection) {
    // use element
}

Read the colon : as “in”“for each element in arrayOrCollection”.

Iterating Over an Array

The most common use is stepping through every element of a plain array.

int[] scores = {88, 92, 74, 95, 61};

for (int score : scores) {
    System.out.println(score);
}

Output:

88
92
74
95
61

Compare this to the equivalent for loop:

for (int i = 0; i < scores.length; i++) {
    System.out.println(scores[i]);
}

Both do the same job, but the for-each version removes the index i entirely — one less variable to name and one less source of bugs.

Iterating Over a Collection

Any class that implements java.lang.Iterable — including all Collections Framework types — works with for-each.

import java.util.List;

List<String> fruits = List.of("Apple", "Mango", "Banana");

for (String fruit : fruits) {
    System.out.println(fruit);
}

Output:

Apple
Mango
Banana

This works equally well with ArrayList, LinkedList, HashSet, TreeSet, and any other Iterable.

Summing Elements

A practical pattern — aggregate values without worrying about index bounds.

double[] prices = {9.99, 14.50, 3.75, 22.00};
double total = 0;

for (double price : prices) {
    total += price;
}

System.out.println("Total: " + total);

Output:

Total: 50.24

Iterating a 2D Array

You can nest for-each loops for multidimensional arrays. The outer loop gives you each row (a int[]), and the inner loop gives you each cell.

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

for (int[] row : matrix) {
    for (int cell : row) {
        System.out.print(cell + " ");
    }
    System.out.println();
}

Output:

1 2 3 
4 5 6 
7 8 9 

Iterating Over an Enum

For-each pairs especially well with enums thanks to the built-in values() method.

enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }

for (Day day : Day.values()) {
    System.out.println(day);
}

Output:

MON
TUE
WED
THU
FRI
SAT
SUN

Limitations — When You Cannot Use for-each

For-each is clean but deliberately restricted. Know when to fall back to a regular for loop or a while loop.

SituationUse instead
You need the current index (e.g., i for position)Traditional for loop
You need to modify the array/list while iteratingTraditional for loop or ListIterator
You only want to iterate part of the collectionTraditional for loop with bounds
You need to iterate in reverseTraditional for loop
You need to remove elements from a CollectionIterator with remove(), or removeIf()

Warning: Modifying a List (adding or removing elements) inside a for-each loop throws a ConcurrentModificationException at runtime. Use list.removeIf(predicate) or an explicit Iterator instead.

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

List<String> names = new ArrayList<>(List.of("Alice", "Bob", "Charlie"));

// WRONG — throws ConcurrentModificationException
// for (String name : names) {
//     if (name.equals("Bob")) names.remove(name);
// }

// CORRECT — use removeIf
names.removeIf(name -> name.equals("Bob"));
System.out.println(names);

Output:

[Alice, Charlie]

Tip: If you need to transform a list while iterating, consider the Stream APIlist.stream().filter(...).collect(...) is expressive and safe.

Modifying Primitive Arrays vs Object Arrays

There is a subtle gotcha with primitive arrays. The loop variable is a copy of the element’s value, so reassigning it does not change the original array.

int[] numbers = {1, 2, 3};

for (int n : numbers) {
    n = n * 10;  // only changes the local copy
}

System.out.println(numbers[0]); // still 1

Output:

1

With objects, the variable holds a reference. You can call mutating methods on the object — but reassigning the variable itself still does not change the collection.

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

List<StringBuilder> builders = new ArrayList<>();
builders.add(new StringBuilder("hello"));
builders.add(new StringBuilder("world"));

for (StringBuilder sb : builders) {
    sb.append("!"); // this DOES modify the object
}

System.out.println(builders); // [hello!, world!]

Output:

[hello!, world!]

Under the Hood

The for-each loop is purely a compiler convenience — the JVM knows nothing special about it.

For arrays, the compiler desugars the loop into a traditional index-based for loop accessing array[i]. You can confirm this with the javap tool — the bytecode is identical to a manual for loop.

For Iterable objects, the compiler expands the loop into an explicit Iterator pattern:

// What you write:
for (String fruit : fruits) {
    System.out.println(fruit);
}

// What the compiler generates (approximately):
Iterator<String> it = fruits.iterator();
while (it.hasNext()) {
    String fruit = it.next();
    System.out.println(fruit);
}

This is why you cannot call it.remove() inside a for-each — you have no access to the hidden Iterator reference. It is also why the ConcurrentModificationException is thrown: the iterator holds a modCount snapshot taken at the start; any structural change to the collection increments the count, and the next hasNext() or next() call detects the mismatch and throws.

Performance is identical to a hand-written iterator loop for collections, and identical to an index loop for arrays — the JIT compiler sees the same bytecode either way. There is zero overhead to choosing for-each when it fits.

Quick Comparison: for vs for-each

FeatureTraditional forfor-each
Index accessYesNo
Works on arraysYesYes
Works on IterableNo (needs .size())Yes
Can remove elementsYes (with care)No (use Iterator)
ReadabilityMediumHigh
Reverse iterationYesNo
Modify elements in-placeArrays: yes; Collections: riskySame risks
  • for Loop — the index-based loop to use when you need position or partial iteration
  • while Loop — when you iterate based on a condition rather than a sequence
  • Iterator — the interface powering for-each under the hood, and the safe way to remove during iteration
  • Stream API — a functional, pipeline-based alternative to looping for transformations and aggregations
  • Arrays Utility Class — static helpers like Arrays.stream() that pair well with for-each patterns
  • Collections Framework — overview of all the Iterable types you can loop with for-each
Last updated June 13, 2026
Was this helpful?