Fundamentals 11 min read

Understanding Java foreach Loop, HashMap Iteration, and ConcurrentModificationException

This article explains how Java's foreach loop is implemented using iterators, demonstrates the bytecode differences between array and collection traversal, analyzes why modifying a HashMap during foreach can trigger ConcurrentModificationException, and shows the correct way to safely modify collections with an iterator.

Architecture Digest
Architecture Digest
Architecture Digest
Understanding Java foreach Loop, HashMap Iteration, and ConcurrentModificationException

When a colleague encountered a ConcurrentModificationException while scanning code with foreach on a HashMap , the author investigated the root cause and discovered that modifying a collection (add, remove, put) during a foreach traversal can cause this exception.

The Java foreach syntax, introduced in JDK 1.5, is syntactic sugar that the compiler translates into either an iterator-based loop for collections or an index-based loop for arrays. The underlying implementation is hidden in the compiler, not in user‑visible code.

Example of a simple foreach over an array:

public class HashMapIteratorDemo {
    String[] arr = {'aa', 'bb', 'cc'};
    public void test1() {
        for (String str : arr) {
            // ...
        }
    }
}

Decompiling the above yields bytecode that is essentially identical to an explicit index loop:

public class HashMapIteratorDemo2 {
    String[] arr = {'aa', 'bb', 'cc'};
    public void test1() {
        for (int i = 0; i < arr.length; i++) {
            String str = arr[i];
        }
    }
}

For collections, foreach is compiled to use an Iterator :

public class HashMapIteratorDemo3 {
    List
list = new ArrayList<>();
    public void test1() {
        list.add(1);
        list.add(2);
        list.add(3);
        for (Integer var : list) {
            // ...
        }
    }
}

And the equivalent explicit iterator version:

public class HashMapIteratorDemo4 {
    List
list = new ArrayList<>();
    public void test1() {
        list.add(1);
        list.add(2);
        list.add(3);
        Iterator
it = list.iterator();
        while (it.hasNext()) {
            Integer var = it.next();
        }
    }
}

Both versions produce nearly identical bytecode, confirming that foreach on collections ultimately invokes Iterator.next() .

When iterating a HashMap with foreach and performing a put that adds a new entry, the program throws ConcurrentModificationException because the underlying iterator detects a mismatch between modCount (actual modifications) and expectedModCount (value captured at iterator creation). The relevant source in HashMap.Node.nextNode() checks this condition and throws the exception.

final Node
nextNode() {
    Node
e = next;
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    // ...
    return e;
}

The remove operation of HashMap also increments modCount , and only the iterator’s own remove() method synchronizes expectedModCount after removal, preventing the exception.

public final void remove() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    // remove node and then
    expectedModCount = modCount; // sync counts
}

Therefore, to safely modify a collection while iterating, one must use the iterator’s remove() method (or other iterator‑provided mutation APIs) instead of calling map.put() or map.remove() directly.

public class HashMapIteratorDemo5 {
    public static void main(String[] args) {
        Map
map = new HashMap<>();
        map.put(1, "aa");
        map.put(2, "bb");
        map.put(3, "cc");
        Iterator
> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry
entry = it.next();
            if (entry.getKey() == 1) {
                it.remove(); // safe removal
            }
        }
    }
}

The article also contains a promotional notice offering a free book titled "程序员书籍资料一份" and a link to a QR‑code for obtaining source code, but the technical discussion remains the core educational content.

JavaHashMapCollectionsIteratorforeachConcurrentModificationException
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.