Question
Given the following Java code:
List<String> someList = new ArrayList<>();
someList.add("monkey");
someList.add("donkey");
someList.add("skeleton key");
for (String item : someList) {
System.out.println(item);
}
What is the equivalent loop written without Java's enhanced for-each syntax?
Also, why do beginners often run into problems when they try to modify the original collection by assigning to the loop variable inside a for-each loop?
Short Answer
By the end of this page, you will understand how Java's enhanced for-each loop works, what code it is roughly equivalent to under the hood, why assigning to the loop variable does not update the original list, and when to use a regular for loop or an Iterator instead.
Concept
Java's enhanced for-each loop is a simpler way to iterate through arrays and collections.
Instead of manually managing an index or an Iterator, you write:
for (String item : someList) {
System.out.println(item);
}
This means:
- take each element from
someList - store it temporarily in
item - run the loop body
- repeat until there are no more elements
For a List, the loop is conceptually similar to using an Iterator:
for (Iterator<String> it = someList.iterator(); it.hasNext(); ) {
String item = it.next();
System.out.println(item);
}
For an array, it behaves more like stepping through indexes from 0 to length - 1.
Why this matters:
- It makes code shorter and easier to read.
- It reduces mistakes involving indexes.
- It is ideal when you only need to read values.
But it also has an important limitation:
Mental Model
Think of a for-each loop like reading names from a printed attendance sheet.
A helper points at each name one at a time and says, "Here is the current one." You can read the name, print it, or use it in calculations.
But if you write a different name on your own notepad, you have not changed the attendance sheet itself.
In this analogy:
- the collection is the attendance sheet
- the loop variable is the name currently handed to you
- assigning a new value to the loop variable is like changing your note, not the original sheet
If you actually want to update the original list, you need a way to write back into the list, such as:
- using an index with
list.set(index, value) - using a
ListIterator - replacing the whole collection content in another way
Syntax and Examples
Basic syntax
for (Type variable : collectionOrArray) {
// use variable
}
Example with a list:
List<String> animals = new ArrayList<>();
animals.add("monkey");
animals.add("donkey");
animals.add("skeleton key");
for (String animal : animals) {
System.out.println(animal);
}
This prints:
monkey
donkey
skeleton key
Equivalent form using an Iterator
For most collections, the enhanced for-each loop is roughly equivalent to:
for (Iterator<String> it = animals.iterator(); it.hasNext(); ) {
String animal = it.next();
System.out.println(animal);
}
Equivalent form using an index
Because this example uses a List, you could also write:
for (int i ; i < animals.size(); i++) {
animals.get(i);
System.out.println(animal);
}
Step by Step Execution
Consider this code:
List<String> items = List.of("monkey", "donkey", "skeleton key");
for (String item : items) {
System.out.println(item);
}
You can think of it as if Java does this:
Iterator<String> it = items.iterator();
while (it.hasNext()) {
String item = it.next();
System.out.println(item);
}
Step by step:
items.iterator()creates an iterator positioned before the first element.it.hasNext()checks whether another element exists.it.next()returns the next element, such as"monkey".- That value is assigned to the loop variable
item. System.out.println(item);prints the current value.- The loop repeats for
"donkey". - The loop repeats for
"skeleton key". - When
hasNext()returnsfalse, the loop stops.
Real World Use Cases
Enhanced for-each loops are common when you want to read each element in a sequence without worrying about indexes.
Common uses
- Printing log messages from a list
- Validating input values one by one
- Summing numbers in an array or collection
- Rendering UI data such as product names or menu items
- Processing API results returned as lists
Example: validating user input
List<String> usernames = List.of("alice", "", "charlie");
for (String username : usernames) {
if (username.isBlank()) {
System.out.println("Invalid username found");
}
}
Example: summing values
int[] numbers = {10, 20, 30};
int total = 0;
for (int number : numbers) {
total += number;
}
System.out.println(total); // 60
When not to use it
Avoid for-each when you need to:
- know the current index
- replace elements in a list
- remove elements during iteration without proper iterator methods
Real Codebase Usage
In real Java projects, developers use enhanced for-each loops mainly for read-only traversal.
Common patterns
1. Read and process each item
for (Order order : orders) {
sendConfirmationEmail(order);
}
2. Validation with guard clauses
for (String email : emails) {
if (email == null || email.isBlank()) {
throw new IllegalArgumentException("Email cannot be empty");
}
}
3. Aggregation
double total = 0;
for (Invoice invoice : invoices) {
total += invoice.getAmount();
}
When developers switch to other tools
Use an index-based loop when replacing list elements
for (int i = 0; i < names.size(); i++) {
names.set(i, names.get(i).trim());
}
Use an Iterator when removing safely during iteration
Common Mistakes
1. Thinking assignment updates the collection
Broken code:
for (String item : items) {
item = "changed";
}
Problem:
- This only changes the local loop variable.
- The list stays the same.
Fix:
for (int i = 0; i < items.size(); i++) {
items.set(i, "changed");
}
2. Removing elements directly from the collection during for-each
Broken code:
for (String item : items) {
if (item.isBlank()) {
items.remove(item);
}
}
Problem:
- This can cause
ConcurrentModificationException.
Fix:
Iterator<String> it = items.iterator();
while (it.hasNext()) {
if (it.next().isBlank()) {
it.remove();
}
}
3. Expecting an index inside for-each
Comparisons
| Approach | Best for | Can access index? | Can replace elements easily? | Can remove safely while iterating? |
|---|---|---|---|---|
Enhanced for-each | Reading elements | No | No | No |
Index-based for loop | Lists and arrays when position matters | Yes | Yes | Sometimes, but must be careful |
Iterator | Safe traversal with removal | No | Not directly | Yes, with remove() |
ListIterator | Traversing and updating lists | Partial |
Cheat Sheet
Enhanced for-each syntax
for (Type variable : collectionOrArray) {
// use variable
}
Equivalent for a collection
for (Iterator<Type> it = collection.iterator(); it.hasNext(); ) {
Type variable = it.next();
// use variable
}
Equivalent for a list if you want indexes
for (int i = 0; i < list.size(); i++) {
Type variable = list.get(i);
}
Key rules
- Works with arrays and
Iterablecollections. - The loop variable is a local variable for the current element.
- Reassigning the loop variable does not update the collection.
- Use
list.set(i, value)to replace elements. - Use
Iterator.remove()to remove safely while iterating.
Remember
FAQ
What is Java's enhanced for loop?
It is a shorter syntax for iterating through arrays and collections without manually writing an index or iterator.
Is a for-each loop the same as a normal for loop?
Not exactly. It can produce the same result, but for collections it is conceptually based on an Iterator, not always an index.
Why doesn't assigning to the loop variable change the list?
Because the loop variable is only a temporary local variable holding the current element reference or value.
Can I remove items inside a Java for-each loop?
Not safely by calling list.remove(...) directly. Use an Iterator and its remove() method.
Can I modify objects inside a for-each loop?
Yes. If the element is a mutable object, you can change the object's internal state. What you cannot do is replace the collection element just by reassigning the loop variable.
When should I use a regular for loop instead?
Use a regular for loop when you need the index or need to replace elements in a list.
Does for-each work on arrays too?
Mini Project
Description
Build a small Java program that displays a list of task names, then creates an updated version of those tasks in uppercase. This project demonstrates the difference between reading with for-each and actually changing list data with an index-based loop.
Goal
Learn when for-each is appropriate and when you must use a different loop to update list contents.
Requirements
Create a list of at least three task names.
Print all tasks using an enhanced for-each loop.
Attempt to uppercase tasks by assigning to the for-each loop variable.
Show that the original list is unchanged.
Use an index-based loop to update the list correctly.
Print the final updated list.
Keep learning
Related questions
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Choosing a @NotNull Annotation in Java: Validation vs Static Analysis
Learn how Java @NotNull annotations differ, when to use each one, and how to choose between validation, IDE hints, and static analysis tools.
Convert a Java Stack Trace to a String
Learn how to convert a Java exception stack trace to a string using StringWriter and PrintWriter, with examples and common mistakes.