ArrayList Iteration in Java
Problem
An ArrayList can be visited with a for-each loop, an explicit Iterator, or a plain index-based loop — all three reach the same elements in the same order, just through different mechanics.
Given an ArrayList of fruits, print its contents three times using a for-each loop, an Iterator, and an index-based loop.
Java Program
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListIteration {
public static void main(String[] args) {
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
System.out.println("For-each loop:");
for (String fruit : fruits) {
System.out.println(fruit);
}
System.out.println("Iterator:");
Iterator<String> it = fruits.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("Index-based loop:");
for (int i = 0; i < fruits.size(); i++) {
System.out.println(fruits.get(i));
}
}
}Output
Core Logic
The for-each loop and the explicit Iterator it's built on both walk forward automatically, while the index-based loop reaches each element by asking for it directly at a given position.
- 1The for-each loop (
for (String fruit : fruits)) is syntactic sugar — under the hood, it creates anIteratorand callshasNext()/next()for you. - 2The explicit
Iterator<String> it = fruits.iterator();loop does the exact same thing by hand, callinghasNext()to check for more elements andnext()to advance and retrieve one. - 3The index-based loop instead calls
fruits.get(i)directly for each index from0tosize() - 1, needing no iterator object at all. - 4All three visit
Apple,Banana, andCherryin that same order, since ArrayList preserves insertion order.
Key Point: An explicit Iterator is the one style that safely supports removing elements mid-loop via it.remove() — modifying the list directly during a for-each or index-based loop risks a ConcurrentModificationException or skipped elements.
Why: Each style visits all n elements exactly once; the for-each loop and explicit Iterator both use the same constant-space iterator object internally, and the index-based loop needs only a single counter variable.
Key Concepts
Approach 2: Java 8
import java.util.ArrayList;
public class ArrayListIterationStream {
public static void main(String[] args) {
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
System.out.println("Stream forEach:");
// No explicit loop construct — the pipeline drives the traversal itself
fruits.stream().forEach(System.out::println);
}
}
Output
Core Logic
A stream's forEach() offers a fourth way to walk the list — a declarative pipeline instead of an explicit loop of any kind.
- 1
fruits.stream()opens a stream over the list's elements, in the same order the list itself holds them. - 2
.forEach(System.out::println)passes a method reference that runs once per element, printing it. - 3Unlike the other three styles, there's no visible loop construct at all — no
for, nowhile, noIteratorvariable. - 4The result still visits
Apple,Banana, andCherryin that same order, since streams over a List preserve encounter order by default.
[Apple, Banana, Cherry] and calling forEach(System.out::println) prints the same three fruits in the same order as the other three styles.Key Point: This is the one style that can't safely remove elements mid-traversal at all — not even the explicit-Iterator way; forEach() is read-only by design, so mutation still belongs to the Iterator style shown in the primary approach.
Why: forEach() still visits each of the n elements exactly once, using a constant amount of extra state to drive the stream.