How to Avoid java.util.ConcurrentModificationException When Removing Elements from a List
This article explains why a foreach loop over an ArrayList can throw java.util.ConcurrentModificationException when removing elements, analyzes the underlying iterator mechanism, and presents three safe alternatives—using Iterator.remove(), a forward-index for loop with index correction, and a reverse for loop—to modify collections without errors.
This article shares a common interview question about encountering a java.util.ConcurrentModificationException when trying to remove elements from an ArrayList using a foreach loop.
It first shows the naive code that causes the exception:
public static void main(String[] args) {
List
platformList = new ArrayList<>();
platformList.add("博客园");
platformList.add("CSDN");
platformList.add("掘金");
for (String platform : platformList) {
if (platform.equals("博客园")) {
platformList.remove(platform);
}
}
System.out.println(platformList);
}Running this code throws java.util.ConcurrentModificationException because the foreach loop internally uses an Iterator , and removing an element directly from the list changes the internal modCount without updating the iterator’s expectedModCount .
The article then explains the iterator’s bytecode, showing that each call to next() invokes checkForComodification() , which compares modCount and expectedModCount . After the explicit remove() call on the list, modCount becomes 4 while expectedModCount remains 3, triggering the exception on the next iteration.
To avoid this problem, three safe approaches are presented:
1. Use Iterator.remove()
By iterating with an Iterator and calling its remove() method, the iterator updates expectedModCount automatically.
public static void main(String[] args) {
List
platformList = new ArrayList<>();
platformList.add("博客园");
platformList.add("CSDN");
platformList.add("掘金");
Iterator
iterator = platformList.iterator();
while (iterator.hasNext()) {
String platform = iterator.next();
if (platform.equals("博客园")) {
iterator.remove();
}
}
System.out.println(platformList);
}The output is [CSDN, 掘金] .
2. Use a forward-index for loop
Iterate by index and adjust the index after removal to avoid skipping elements.
public static void main(String[] args) {
List
platformList = new ArrayList<>();
platformList.add("博客园");
platformList.add("CSDN");
platformList.add("掘金");
for (int i = 0; i < platformList.size(); i++) {
String item = platformList.get(i);
if (item.equals("博客园")) {
platformList.remove(i);
i = i - 1; // correct the index after removal
}
}
System.out.println(platformList);
}Adjusting i ensures the next element is not missed.
3. Use a reverse for loop
Iterate from the end of the list toward the beginning; removal does not affect the indices of the yet‑to‑be‑processed elements.
public static void main(String[] args) {
List
platformList = new ArrayList<>();
platformList.add("博客园");
platformList.add("CSDN");
platformList.add("掘金");
for (int i = platformList.size() - 1; i >= 0; i--) {
String item = platformList.get(i);
if (item.equals("掘金")) {
platformList.remove(i);
}
}
System.out.println(platformList);
}This method avoids index correction because elements after the current index are already processed.
In summary, the article demonstrates why modifying a collection during a foreach iteration leads to ConcurrentModificationException and provides three reliable ways—using Iterator.remove() , a forward-index loop with index adjustment, and a reverse loop—to safely remove elements from a list.
Architect's Tech Stack
Java backend, microservices, distributed systems, containerized programming, and more.
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.