Why Using forEach to Remove Elements from an ArrayList Throws ConcurrentModificationException and How to Delete Safely
The article explains why iterating an ArrayList with forEach and removing elements causes a ConcurrentModificationException, analyzes the underlying fail‑fast iterator behavior, and presents three correct ways—using Iterator.remove, removeIf, and collecting then removing—to delete elements safely.
Programmers with 1‑3 years of experience are considered junior, while those with more experience are senior, but a recent code review revealed a five‑year‑veteran using ArrayList with forEach to delete elements, which leads to a runtime error.
1. Reproduction
The following code (with sensitive parts anonymized) demonstrates the issue:
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(Arrays.asList("1", "2", "3"));
list.forEach(item -> {
if (item.startsWith("1")) {
list.remove(item);
}
});
}Running this code throws a ConcurrentModificationException because the list is modified while it is being iterated.
2. Cause Analysis
The forEach construct is syntactic sugar; after compilation it becomes equivalent to the following loop:
// This is the sugar expanded by the compiler
for (Iterator i = lists.iterator(); i.hasNext(); ) {
String s = (String) i.next();
if (s.startsWith("1")) {
list.remove(s);
}
}The Iterator.next() method checks for concurrent modification and throws ConcurrentModificationException if the underlying collection has been altered, because ArrayList 's iterator is designed to be fail‑fast.
3. Correct Deletion Methods
3.1 Use Iterator.remove
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (item.startsWith("1")) {
iterator.remove();
}
}This approach removes elements without breaking the iterator's state.
3.2 Use removeIf (Java 8+)
list.removeIf(item -> item.startsWith("1")); removeIfprovides a concise, safe way to delete matching elements.
3.3 Collect then removeAll
List<String> itemsToRemove = list.stream()
.filter(item -> item.startsWith("1"))
.collect(Collectors.toList());
list.removeAll(itemsToRemove);This method first gathers the elements to be removed and then deletes them in a single operation.
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.
IT Services Circle
Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.
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.
