Calling remove in foreach loop in Java
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Removing elements from a Java collection while iterating over it is a common source of bugs. The short version is that you should not call the collection's own remove method from inside an enhanced for loop, because that loop is backed by an iterator and structural changes made behind the iterator's back trigger fail-fast behavior.
Why foreach Removal Fails
The enhanced for loop is syntax sugar for iterator-based traversal. When you write this:
Java is effectively using an iterator under the hood. That iterator expects the collection structure to remain unchanged except through the iterator itself. If the collection is modified directly, the iterator notices that its internal modification count no longer matches the collection, and a ConcurrentModificationException is usually thrown.
A minimal example is:
This pattern is unsafe even if it appears to work occasionally with certain inputs.
Use the Iterator's remove Method Instead
If you need to remove elements during iteration, iterate explicitly with an Iterator and call iterator.remove().
This works because the iterator updates its own internal state when removal happens through its API.
Use removeIf When You Only Need Filtering
If your goal is simply "remove every element matching this condition," Java 8 added a cleaner option: removeIf.
This is usually the most readable approach because the collection handles the iteration internally.
When a Two-Phase Approach Is Better
Sometimes removal is only one part of a larger loop body, and collecting items first is easier to reason about. In that case, gather the elements to remove and perform the structural update after iteration finishes.
This is slightly more verbose, but it keeps the iteration logic separate from the structural change, which can make complex code easier to maintain.
Common Pitfalls
The biggest mistake is assuming foreach is independent from iterators. It is not. The iterator is still there, just hidden by syntax sugar.
Another mistake is switching to an index-based loop without thinking about shifting indices. That can work for lists, but careless index removal can skip elements or throw bounds errors.
Developers also sometimes hear the term ConcurrentModificationException and assume multiple threads are involved. In many cases, there is no thread concurrency at all. The name refers to modifying the collection while it is being iterated, not necessarily to multithreading.
Finally, iterator.remove() only removes the current element after a successful next() call. Calling it at the wrong time causes its own exception.
Summary
- Do not call the collection's
removemethod inside an enhancedforloop. - Enhanced
forloops are backed by iterators and usually fail fast on structural modification. - Use
Iterator.remove()when you must remove while iterating. - Use
removeIffor simple predicate-based filtering. - For more complex cases, collect items first and remove them afterward.

