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 List inside a foreach loop, which immediately throws java.util.ConcurrentModificationException.
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);
}The foreach construct is compiled to use an Iterator whose core methods are hasNext() and next(). During each next() call the iterator invokes checkForComodification(), which compares the collection’s internal modCount with an expectedModCount. Removing an element directly from the list changes modCount but not expectedModCount, causing the mismatch and the exception.
Therefore, foreach cannot be used for removal.
2. Use Iterator.remove() Method
Iterating with an explicit Iterator and calling its remove() safely updates expectedModCount.
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);
}[CSDN, 掘金]
Each call to iterator.remove() resets expectedModCount to 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.
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);
}After removing an element the list shrinks, so the next element shifts to the current index; decrementing i ensures the shifted element is not skipped.
i = i - 1;4. Use Reverse for Loop
Iterating from the end avoids index correction because removal does not affect the yet‑to‑visit elements.
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);
}Since the loop proceeds backward, removing an element does not shift the indices of the remaining elements that are still to be processed.
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.
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.
