GotchaDifficulty: Advanced1 min

ConcurrentModificationException: Removing Inside a for-each Loop

A single-threaded loop that removes cancelled orders, and an exception that mentions concurrency.

Removing an element through the list while an enhanced for loop is walking it usually throws ConcurrentModificationException, even with a single thread. The loop uses an iterator (the object that walks a collection one element at a time), and the iterator detects that the list changed underneath it and refuses to continue.

A loop that removes the cancelled orders, whose references start with X, from a list:

java
for (String ref : refs) {
    if (ref.startsWith("X")) {
        refs.remove(ref);
    }
}
text
Exception in thread "main" java.util.ConcurrentModificationException

The enhanced for uses an iterator, and the iterator keeps a count of how many times the list has been structurally changed. Removing through the list bumps that count without telling the iterator, so the next step notices the mismatch and refuses to continue.

There are three ways out, in order of how often each is the right one:

java
refs.removeIf(ref -> ref.startsWith("X"));

Iterator<String> it = refs.iterator();
while (it.hasNext()) {
    if (it.next().startsWith("X")) { it.remove(); }
}

List<String> kept = refs.stream().filter(ref -> !ref.startsWith("X")).toList();

removeIf is one line and says what it means. The iterator's own remove is the general answer when the condition needs more than an expression. Building a new list is the right answer when the original should not change at all.