Course topics

By WebNest Studio Engineering Team

Java - Core Tutorial

Java For-each Loop

The for-each loop (also called the "enhanced for loop"), introduced in Java 5, provides a simpler syntax for iterating over every element of an array or any object implementing Iterable, such as the collections in java.util. It removes the need to manage an index variable manually, which eliminates an entire category of off-by-one and ArrayIndexOutOfBoundsException bugs.

The syntax reads almost like plain English: for (Type element : collection) means "for each element of this type in this collection." Internally, for an array the compiler generates an equivalent indexed loop, and for an Iterable it generates calls to hasNext() and next() on an iterator — but you never have to write that machinery yourself.

Why it matters

The for-each loop removes the index, and with it a whole category of off-by-one mistakes, so it is the default way to read every element of an array or collection. Knowing its limits matters just as much: it cannot change which element an array holds, and removing from a collection inside one throws an exception that surprises most developers the first time.

Syntax and How It Works

On each iteration, the loop variable is assigned a copy of the next element in the array or collection, in order, and the body executes with that value available. The loop automatically stops after the last element, so there is no condition or index update to get wrong.

Watch: How the Java For-each Loop Works Internally

A quick video on what the compiler turns a for-each loop into for arrays and collections.

Watch on YouTube

How It Works Internally: What the Compiler Generates

There is no special "for-each" instruction in the JVM. The compiler rewrites every enhanced for loop into an ordinary loop before producing bytecode, and it picks one of two shapes depending on what you loop over:

  • Arrays become an indexed loop. for (int n : nums) { ... } is compiled as if you wrote int[] a = nums; for (int i = 0; i < a.length; i++) { int n = a[i]; ... }. The array reference is captured once before the loop starts, so pointing nums at a different array inside the body does not change what is being iterated.
  • Anything Iterable (List, Set, Queue, your own classes) becomes an iterator loop. for (String s : list) { ... } is compiled as for (Iterator<String> it = list.iterator(); it.hasNext(); ) { String s = it.next(); ... }.
  • The loop variable is a fresh local variable assigned from a[i] or it.next() on every pass. That is why reassigning it never changes the array or collection — for objects it is a copy of the reference, so calling a method that changes the object itself (like sb.append("!")) does affect the original.
  • Because the generated code calls list.iterator() (for a collection) or reads a.length (for an array) before the first pass, looping over a null collection or array throws a NullPointerException before the body ever runs.
  • Any class that implements Iterable<T> — that is, has an iterator() method — can be used in a for-each loop. Maps are not Iterable themselves, which is why you loop over map.entrySet(), keySet() or values() instead.

Why Removing Inside for-each Throws ConcurrentModificationException

Collections like ArrayList keep an internal modification counter (modCount) that increases every time the list changes size. When the hidden iterator is created, it remembers that count. Every call to next() compares the two, and if the list was changed behind the iterator's back — for example by list.remove(x) inside the loop — it throws ConcurrentModificationException. This is a "fail-fast" safety check, not a threading problem. The fix is to remove through the iterator itself with an explicit Iterator and it.remove(), which updates both counters together, or to use list.removeIf(...), which does the same thing in one line.

Limitations of the For-each Loop

The convenience comes with real trade-offs that make for-each unsuitable for some tasks.

  • The loop variable holds a copy of each element for primitives, so reassigning it inside the loop body does not modify the original array.
  • There is no automatic access to the current index, which is a problem if you need to know an element's position or modify the array in place by index.
  • You cannot easily iterate backward, skip elements, or iterate two collections in lockstep using a single for-each loop.
  • You cannot safely add or remove elements from most collections while iterating over them with for-each — doing so throws a ConcurrentModificationException.

Examples

Iterating an int array and a String array with for-each

Java
public class ForEachDemo {
    public static void main(String[] args) {
        int[] numbers = {2, 4, 6, 8, 10};
        int sum = 0;
        for (int num : numbers) {
            sum += num;
        }
        System.out.println("Sum: " + sum);

        String[] fruits = {"Apple", "Banana", "Cherry"};
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}
Output
Sum: 30
Apple
Banana
Cherry

What the compiler turns a for-each loop into, written out by hand for an array and a List

Java
import java.util.Iterator;
import java.util.List;

public class ForEachInternalsDemo {
    public static void main(String[] args) {
        int[] nums = {10, 20, 30};

        // What you write
        for (int n : nums) {
            System.out.print(n + " ");
        }
        System.out.println("<- for-each over array");

        // What the compiler generates for an array
        int[] a = nums;
        for (int i = 0; i < a.length; i++) {
            int n = a[i];
            System.out.print(n + " ");
        }
        System.out.println("<- indexed loop");

        List<String> langs = List.of("Java", "Python", "React");

        // What you write
        for (String s : langs) {
            System.out.print(s + " ");
        }
        System.out.println("<- for-each over List");

        // What the compiler generates for an Iterable
        for (Iterator<String> it = langs.iterator(); it.hasNext(); ) {
            String s = it.next();
            System.out.print(s + " ");
        }
        System.out.println("<- iterator loop");
    }
}
Output
10 20 30 <- for-each over array
10 20 30 <- indexed loop
Java Python React <- for-each over List
Java Python React <- iterator loop

Your own class works in for-each as soon as it implements Iterable

Java
import java.util.Iterator;

public class CountdownDemo {
    static class Countdown implements Iterable<Integer> {
        private final int start;

        Countdown(int start) {
            this.start = start;
        }

        @Override
        public Iterator<Integer> iterator() {
            return new Iterator<>() {
                private int current = start;

                @Override
                public boolean hasNext() {
                    return current > 0;
                }

                @Override
                public Integer next() {
                    return current--;
                }
            };
        }
    }

    public static void main(String[] args) {
        for (int n : new Countdown(5)) {
            System.out.print(n + " ");
        }
        System.out.println("Liftoff!");
    }
}
Output
5 4 3 2 1 Liftoff!

Removing inside for-each fails fast; Iterator.remove() and removeIf() are the safe ways

Java
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;

public class SafeRemoveDemo {
    public static void main(String[] args) {
        List<Integer> nums = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
        try {
            for (int n : nums) {
                if (n % 2 == 0) {
                    nums.remove(Integer.valueOf(n));
                }
            }
        } catch (ConcurrentModificationException e) {
            System.out.println("for-each + list.remove(): ConcurrentModificationException");
        }

        List<Integer> a = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
        for (Iterator<Integer> it = a.iterator(); it.hasNext(); ) {
            if (it.next() % 2 == 0) {
                it.remove();
            }
        }
        System.out.println("Iterator.remove(): " + a);

        List<Integer> b = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
        b.removeIf(n -> n % 2 == 0);
        System.out.println("removeIf():        " + b);
    }
}
Output
for-each + list.remove(): ConcurrentModificationException
Iterator.remove(): [1, 3, 5]
removeIf():        [1, 3, 5]

Common Mistakes

  • Trying to modify an array element by assigning to the for-each loop variable, not realizing it only changes the local copy, not the array.
  • Looping over a collection that might be null — the hidden iterator() call throws a NullPointerException before the first iteration, so return an empty list instead of null.
  • Trying to use a Map directly in a for-each loop; Map is not Iterable, so loop over entrySet(), keySet() or values().
  • Needing the current index inside the loop and having no clean way to get it without falling back to an indexed for loop.
  • Adding or removing elements from a List while iterating it with for-each, which throws a ConcurrentModificationException at runtime.
  • Assuming for-each can iterate in reverse order — it always moves forward from the first element to the last.

Exercise

Find the largest value in an array using a for-each loop, without using any library method.

Expected output: 89

Java · starter code
public class LargestValue {
    public static void main(String[] args) {
        int[] scores = {12, 45, 7, 89, 23};

        // TODO: find the largest value with a for-each loop

        System.out.println(largest);
    }
}
Show hints
  • Start by assuming the first element is the largest, then compare every element against it.
  • The loop reads as "for each score in scores": for (int score : scores).
Show solution
Java · solution
public class LargestValue {
    public static void main(String[] args) {
        int[] scores = {12, 45, 7, 89, 23};

        int largest = scores[0];
        for (int score : scores) {
            if (score > largest) {
                largest = score;
            }
        }

        System.out.println(largest); // 89
    }
}

Quick quiz

1. Given int[] nums = {1, 2, 3};, what does the array contain after for (int n : nums) { n = n * 2; }?

  • A. {2, 4, 6}
  • B. {0, 0, 0}
  • C. {1, 2, 3}
  • D. It does not compile
Show answer

C. n is a copy of each element. Assigning to it changes only the local variable, not the array.

2. What happens when you call list.remove(item) on an ArrayList inside a for-each loop over that same list?

  • A. The item is removed safely
  • B. The loop restarts
  • C. It does not compile
  • D. It usually throws ConcurrentModificationException
Show answer

D. The loop uses an iterator that detects the list was changed behind its back and throws ConcurrentModificationException. Use Iterator.remove() or removeIf() instead.

3. What must your own class implement to be usable in a for-each loop?

  • A. Iterable
  • B. Comparable
  • C. Serializable
  • D. Cloneable
Show answer

A. for-each works on arrays and on any object that implements Iterable, which supplies an Iterator.

Interview questions

What are the limitations of the for-each loop?

Show answer

You have no index, so you cannot easily tell the position of an element, iterate backwards, skip elements, or walk two arrays in step. You cannot replace an element of an array through the loop variable, and you cannot safely remove from the collection you are iterating. When any of those is needed, use an indexed for loop or an explicit Iterator.

How does the for-each loop work internally?

Show answer

It is compiler shorthand. For an array, the compiler generates an ordinary indexed loop from 0 to length. For anything else, it calls iterator() on the Iterable and loops with hasNext() and next(). That hidden iterator is why modifying a collection inside the loop is detected.

Key Points to Remember

  • for-each works on arrays and any type implementing Iterable, without managing an index manually.
  • The loop variable receives a copy of each element; reassigning it never changes the underlying array or collection.
  • for-each has no built-in index access and always iterates forward only.
  • Modifying a collection's structure while iterating it with for-each can throw ConcurrentModificationException.
  • Internally, for-each over an array compiles to an indexed loop, and over an Iterable to an iterator loop using hasNext() and next().
  • Any class implementing Iterable can be used in for-each; to remove while looping, use Iterator.remove() or removeIf().

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering