Fundamentals 9 min read

Why Adding or Removing Elements Inside a Java foreach Loop Fails

This article explains why modifying a collection during a Java foreach loop triggers a ConcurrentModificationException, explores the underlying fail‑fast mechanism in ArrayList, and demonstrates safe alternatives such as using an Iterator's remove method or a CopyOnWriteArrayList.

Programmer DD
Programmer DD
Programmer DD
Why Adding or Removing Elements Inside a Java foreach Loop Fails

ArrayList

A classic interview question asks why you cannot add or remove elements inside a Java foreach loop. The article analyzes this restriction and demonstrates the resulting ConcurrentModificationException.

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    // Populate list
    for (int i = 0; i < 10; i++) {
        list.add(i + "");
    }
    for (String s : list) {
        if ("5".equals(s)) {
            list.remove(5);
        }
        System.out.println(s);
    }
}

Running this code produces:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
    at java.util.ArrayList$Itr.next(ArrayList.java:861)

The reason is that the foreach construct is compiled to use an Iterator internally. When the underlying list is modified directly, the iterator detects a mismatch between modCount and expectedModCount and throws the exception.

In ArrayList, modCount tracks the number of structural modifications. The remove methods increment this counter:

public E remove(int index) {
    rangeCheck(index);
    modCount++;
    E oldValue = elementData(index);
    // shift elements, clear last slot, adjust size
    return oldValue;
}

public boolean remove(Object o) {
    // ...
    fastRemove(index);
    return true;
}

private void fastRemove(int index) {
    modCount++;
    // shift elements, clear last slot
}

The iterator stores the value of modCount at creation as expectedModCount: final int expectedModCount = modCount; If modCount changes without the iterator's knowledge, checkForComodification throws the exception, implementing the fail‑fast mechanism.

To avoid the exception, use the iterator's own remove method:

public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        list.add(i);
    }
    Iterator<Integer> iterator = list.iterator();
    while (iterator.hasNext()) {
        Integer integer = iterator.next();
        if (integer == 5) {
            iterator.remove(); // safe removal
        }
    }
    System.out.println(list);
}

This prints [0, 1, 2, 3, 4, 6, 7, 8, 9] without error.

Another alternative is CopyOnWriteArrayList, which creates a fresh copy of the underlying array on each write, thus isolating the iterator from concurrent modifications:

public static void main(String[] args) {
    CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
    for (int i = 0; i < 10; i++) {
        list.add(i);
    }
    Iterator<Integer> iterator = list.iterator();
    while (iterator.hasNext()) {
        Integer integer = iterator.next();
        if (integer == 5) {
            list.remove(Integer.valueOf(5)); // safe removal
        }
    }
    System.out.println(list);
}

While this also works, it incurs extra memory and copying overhead, which is why it is less commonly recommended.

In summary, the foreach loop cannot safely add or remove elements because it relies on a fail‑fast iterator that checks for structural changes via modCount. Using the iterator's remove method or a CopyOnWriteArrayList are the proper ways to modify a collection during iteration.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaArrayListIteratorforeachConcurrentModificationExceptionfail-fast
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

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.