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
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
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"));removeIf provides a concise, safe way to delete matching elements.
3.3 Collect then removeAll
List
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.
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.