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.
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:
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
