Java Enhanced for Loop
Table of Contents + −
In the last lesson you learned about the Java do-while loop. Every loop so far makes you manage a counter by hand, which is a lot of bookkeeping just to visit every item in a list.
So Java gives you a cleaner option made for exactly this: the enhanced for loop, also called the for-each loop.
🤔 Why do we need a for-each loop?
To print an array of names, a normal for loop makes you manage a counter by hand:
String[] names = {"Alex", "Riya", "Arjun"};for (int i = 0; i < names.length; i++) { System.out.println(names[i]);}That is a lot of parts to get right just to say “print every name”, and each is a place for a bug:
- Start
iat the right value, or you skip an item. - Wrong sign (
<=instead of<) reads past the end. - A forgotten
i++makes the loop run forever. - A wrong index reaches the wrong slot.
None of this is about names. It is all just bookkeeping.
Like reading a guest list, you only care about the name, not that “Riya” is guest number two. The for-each loop hands you each item and skips all the counting.
🧩 The enhanced for loop syntax
The for-each loop reads almost like a sentence:
for (Type item : collection) { // use item here, one element at a time}Read the : as “in”, so the line says “for each item in collection”:
- No index, no condition, no update step. Java does that for you.
- Each pass puts the next element into
item. You useitemdirectly. - The one rule: the type before the variable must match the elements. Use
Stringfor an array of strings,intfor an array of ints.
💡 A simple example
The same array of names, now with a for-each loop:
String[] names = {"Alex", "Riya", "Arjun"};for (String name : names) { System.out.println(name);}“For each name in names, print the name”:
- The loop variable
nameholds"Alex", then"Riya", then"Arjun". - The array is then finished, so the loop stops on its own.
- No
i, nonames.length, noi++.
Output
AlexRiyaArjunThe loop knows the collection’s length already, so it ends exactly when there are no more items. One less thing to get wrong.
🖥️ A more real example
The for-each loop shines when you process values. Here we add up student marks to find the total.
public class TotalMarks { public static void main(String[] args) { int[] marks = {85, 90, 78, 92, 88}; int total = 0;
for (int mark : marks) { total = total + mark; }
System.out.println("Total marks: " + total); }}Step by step:
totalstarts at0, our running sum.- For each
mark, we add it tototal. - When the loop ends,
totalholds the sum of every mark.
We never touched an index. We only cared about the values. That is the sweet spot for for-each: visit every item and do something with each value.
Output
Total marks: 433📋 It works on more than arrays
The for-each loop works on any Iterable, Java’s word for “something you can step through one item at a time”:
- Arrays, but also a
List, aSet, and many other collections. - The same clean syntax carries over to all of them.
Here we build a small List of cities, then print each one:
import java.util.List;
public class Cities { public static void main(String[] args) { List<String> cities = List.of("London", "Tokyo", "Cairo");
for (String city : cities) { System.out.println(city); } }}The loop body did not change. Array or list, “for each city in cities” reads and works the same.
Output
LondonTokyoCairoA Set works too. It holds items with no duplicates and no promised order, so a counter-based loop would be awkward there.
The for-each loop does not care about order, it just asks for each item in turn:
import java.util.Set;
public class UniqueTags { public static void main(String[] args) { Set<String> tags = Set.of("java", "loops", "basics");
for (String tag : tags) { System.out.println(tag); } }}Set order is not fixed
A Set does not promise any particular order. So the three tags may print in a different order than you typed them. That is normal for a plain Set. The for-each loop still visits each item exactly once.
🚫 The limits of for-each
The for-each loop is clean because it hides things, but hiding means you give up control. So there are jobs it cannot do. These limits tell you when to reach for a normal for instead:
- You cannot get the index. There is no
i, so you never know “this is item number 3”. If you need the position, for-each cannot give it to you. - You cannot change a primitive element through the loop variable. For
int,double,charand the like, the loop variable is a copy of the value. Editing the copy does nothing to the array. - You cannot safely remove items while looping a collection. Removing from a list or set inside a for-each throws a
ConcurrentModificationException. - You cannot easily walk two arrays together. With a shared index
iyou can reada[i]andb[i]side by side. A for-each gives only one stream of values. - You cannot go backwards. A for-each always runs front to back. To go last-to-first you need a counter you control.
The copy point surprises people, so let’s make it concrete. Here we try to double every number by setting each n to n * 2, then print the array:
int[] numbers = {1, 2, 3};
for (int n : numbers) { n = n * 2; // ❌ changes the copy, not the array}
System.out.println(numbers[0] + " " + numbers[1] + " " + numbers[2]);You might expect 2 4 6, but you get the original values back:
Output
1 2 3Why? n is a fresh copy of each element. Changing it changes the copy, which is thrown away on the next pass, so the array slot is never touched.
To really edit the array, loop by index and assign to numbers[i]:
int[] numbers = {1, 2, 3};
for (int i = 0; i < numbers.length; i++) { numbers[i] = numbers[i] * 2; // ✅ writes back into the array}
System.out.println(numbers[0] + " " + numbers[1] + " " + numbers[2]);Output
2 4 6The removal limit matters too:
- Call
removeinside a for-each and Java notices the collection changed, then crashes with aConcurrentModificationException. - To remove while looping, use an
Iteratorand itsremovemethod, or build a new list. - Plain for-each is for reading, not removing.
🔁 for-each vs the normal for loop
Both loops can walk an array, so when do you pick which? The simple split:
- Enhanced for when you just need the values and do not care about positions. Shorter and safer, read-only in spirit.
- Normal for when you need the index: to change elements, go backwards, skip items, or read two arrays together.
This table sums up the trade-off:
| What you need | Best choice |
|---|---|
| Just read each value | Enhanced for (for-each) |
| Know the position of each item | Normal for |
| Change array elements | Normal for |
| Go backwards or skip items | Normal for |
| Loop two arrays side by side | Normal for |
You cannot get the index in a for-each
The enhanced for loop hides the index from you on purpose. So if you need to know “this is item number 3”, or you want to modify the array at a position, the for-each loop will not help. Use a normal for loop with an index for those jobs.
⚠️ Common Mistakes
A few for-each slip-ups, each with the wrong way then the fix.
Trying to use an index that is not there. A for-each has no i, so you cannot ask for a position.
for (String name : names) { System.out.println(i + ": " + name); // ❌ no i exists here}
for (int i = 0; i < names.length; i++) { System.out.println(i + ": " + names[i]); // ✅ normal for gives you i}Wrong element type. The type before the variable must match the elements. The items in an int[] are int, not String.
int[] marks = {85, 90, 78};
for (String m : marks) { // ❌ will not compile, items are int System.out.println(m);}
for (int m : marks) { // ✅ type matches the elements System.out.println(m);}Expecting changes to the loop variable to stick. For primitives the loop variable is a copy, so assigning to it does nothing to the array.
for (int n : numbers) { n = 0; // ❌ only zeroes the copy}
for (int i = 0; i < numbers.length; i++) { numbers[i] = 0; // ✅ actually zeroes the array}Removing from a collection while you loop it. This throws a ConcurrentModificationException at runtime.
for (String city : cities) { cities.remove(city); // ❌ crashes mid-loop}
cities.removeIf(city -> city.equals("Tokyo")); // ✅ safe, no manual loop✅ Best Practices
Habits for clean for-each loops:
- Reach for it when you only need values. Reading and processing every item is what it is for.
- Name the loop variable as a singular.
namefornames,markformarks. Then it reads like plain English. - Switch to a normal for when you need the index. Modifying elements, going in reverse, skipping, or pairing two arrays all need an index.
- Do not remove inside a for-each. Use
removeIf, anIterator, or build a new list. - Keep the body short. A for-each is meant to be easy to read.
🧩 What You’ve Learned
Nicely done. Quick recap:
- ✅ The enhanced for loop (for-each) goes through every item in an array or collection without an index.
- ✅ The syntax reads as “for each item in collection”:
for (Type item : collection), where the:means “in”. - ✅ It works on arrays and any Iterable, like
ListandSet. - ✅ It is shorter and safer than a normal
forbecause there is no counter to manage. - ✅ Its limits: no index, you cannot change a primitive element through the loop variable, you cannot remove while looping, and you cannot easily go backwards or pair two arrays.
- ✅ Use a normal for loop when you need the index, want to modify elements, or go backwards.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does the enhanced for loop give you on each pass?
Why: A for-each loop hands you each value one at a time, with no index involved.
- 2
How do you read the loop `for (String name : names)`?
Why: The colon means 'in', so it reads 'for each name in names'.
- 3
When should you use a normal for loop instead of a for-each?
Why: The for-each hides the index, so anything needing positions or element changes needs a normal for loop.
- 4
What happens if you assign a new value to the loop variable in `for (int n : numbers)`?
Why: For primitives the loop variable is a copy, so changing it does not touch the original array.
🚀 What’s Next?
Sometimes you need to stop a loop early, before it would normally finish. Like when you find what you were searching for. Java has a keyword just for that: break. Let’s see how it works.