Avoid ConcurrentModificationException: Safe Ways to Remove Elements While Iterating in Java
This article explains why removing items from a Java List inside a foreach loop triggers java.util.ConcurrentModificationException and demonstrates three reliable alternatives—using Iterator.remove(), a forward for‑loop with index adjustment, and a reverse for‑loop—to safely modify collections during iteration.
1. Common Mistake by Beginners
Many beginners try to remove elements from a
Listinside a foreach loop, which immediately throws
java.util.ConcurrentModificationException.
<code>public static void main(String[] args) {
List<String> platformList = new ArrayList<>();
platformList.add("博客园");
platformList.add("CSDN");
platformList.add("掘金");
for (String platform : platformList) {
if (platform.equals("博客园")) {
platformList.remove(platform);
}
}
System.out.println(platformList);
}
</code>The foreach construct is compiled to use an
Iteratorwhose core methods are
hasNext()and
next(). During each
next()call the iterator invokes
checkForComodification(), which compares the collection’s internal
modCountwith an
expectedModCount. Removing an element directly from the list changes
modCountbut not
expectedModCount, causing the mismatch and the exception.
Therefore, foreach cannot be used for removal.
2. Use Iterator.remove() Method
Iterating with an explicit
Iteratorand calling its
remove()safely updates
expectedModCount.
<code>public static void main(String[] args) {
List<String> platformList = new ArrayList<>();
platformList.add("博客园");
platformList.add("CSDN");
platformList.add("掘金");
Iterator<String> iterator = platformList.iterator();
while (iterator.hasNext()) {
String platform = iterator.next();
if (platform.equals("博客园")) {
iterator.remove();
}
}
System.out.println(platformList);
}
</code>[CSDN, 掘金]
Each call to
iterator.remove()resets
expectedModCountto the current
modCount, keeping them equal and preventing the exception.
3. Use Forward for Loop
Iterating with an index allows removal, but the index must be adjusted after each deletion.
<code>public static void main(String[] args) {
List<String> 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;
}
}
System.out.println(platformList);
}
</code>After removing an element the list shrinks, so the next element shifts to the current index; decrementing
iensures the shifted element is not skipped.
<code>i = i - 1;
</code>4. Use Reverse for Loop
Iterating from the end avoids index correction because removal does not affect the yet‑to‑visit elements.
<code>public static void main(String[] args) {
List<String> 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);
}
</code>Since the loop proceeds backward, removing an element does not shift the indices of the remaining elements that are still to be processed.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.