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.
| Situation | Use instead |
|---|---|
You need the current index (e.g., i for position) | Traditional for loop |
| You need to modify the array/list while iterating | Traditional for loop or ListIterator |
| You only want to iterate part of the collection | Traditional for loop with bounds |
| You need to iterate in reverse | Traditional for loop |
You need to remove elements from a Collection | Iterator with remove(), or removeIf() |
Warning: Modifying a
List(adding or removing elements) inside a for-each loop throws aConcurrentModificationExceptionat runtime. Uselist.removeIf(predicate)or an explicitIteratorinstead.
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 API —
list.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
| Feature | Traditional for | for-each |
|---|---|---|
| Index access | Yes | No |
| Works on arrays | Yes | Yes |
Works on Iterable | No (needs .size()) | Yes |
| Can remove elements | Yes (with care) | No (use Iterator) |
| Readability | Medium | High |
| Reverse iteration | Yes | No |
| Modify elements in-place | Arrays: yes; Collections: risky | Same risks |
Related Topics
- 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
Iterabletypes you can loop with for-each