Fundamentals 5 min read

Why Removing Elements in a Java foreach Loop Can Crash Your Code

This article explains why using a foreach loop to remove items from a Java ArrayList can trigger a ConcurrentModificationException, analyzes the underlying iterator mechanism, and shows the correct way to modify collections safely with an explicit Iterator.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why Removing Elements in a Java foreach Loop Can Crash Your Code

In Java programming, using an ArrayList with a foreach loop to remove elements may cause a ConcurrentModificationException . The following two code snippets illustrate the problem:

List<String> arrayList1 = new ArrayList<String>();
arrayList1.add("1");
arrayList1.add("2");
for (String s : arrayList1) {
    if ("1".equals(s)) {
        arrayList1.remove(s);
    }
}

List<String> arrayList2 = new ArrayList<String>();
arrayList2.add("2");
arrayList2.add("1");
for (String s : arrayList2) {
    if ("1".equals(s)) {
        arrayList2.remove(s);
    }
}

Running the code shows that arrayList1 removes the element successfully, while arrayList2 throws a ConcurrentModificationException.

The remove call succeeds for arrayList1 , but the same call for arrayList2 results in a ConcurrentModificationException .

The reason lies in the fact that a foreach loop is implemented using an Iterator. All collection classes implement the Iterable interface, and ArrayList provides an internal Itr class that implements Iterator:

ArrayList iterator implementation
ArrayList iterator implementation

The iterator works by calling hasNext() to check for a next element and then next() to retrieve it. In arrayList1, the loop iterates only once; after removing "1", the list size becomes 1 and the iterator’s cursor moves to 1, ending the loop without error.

In arrayList2, after removing "1" on the second iteration, the iterator’s cursor becomes 2 while the list size is now 1. When next() is called again, the iterator detects that the list’s modCount has changed (it was incremented by the removal) while its internal expectedModCount remains unchanged, causing the ConcurrentModificationException.

Because both remove and add operations increment modCount, modifying an ArrayList inside a foreach loop is unsafe.

The recommended approach is to use an explicit Iterator and its remove() method:

Iterator<String> iterator = arrayList2.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if ("1".equals(item)) {
        iterator.remove();
    }
}

If the collection may be accessed concurrently, the iterator should be protected with appropriate locking.

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.

JavaprogrammingCollectionsArrayListIteratorConcurrentModificationException
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

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.