<code>Iterator</code> and <code>removeIf</code> in Java
Iterator is the interface every Java collection exposes to walk through its elements one at a time. Three methods: hasNext(), next(), remove(). The enhanced for loop is syntactic sugar over it.
The basic contract
var it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.isEmpty()) it.remove(); // β
safe removal
}
remove() removes the element last returned by next(). Calling it before next() or twice in a row throws IllegalStateException.
The enhanced for under the hood
for (String s : list) send(s);
// Is equivalent to:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
send(s);
}
removeIf β the modern idiom (Java 8+)
list.removeIf(String::isEmpty);
list.removeIf(user -> user.age() < 18);
map.entrySet().removeIf(e -> e.getValue() == null);
Cleaner than an explicit iterator loop, and the implementation batches the work for better performance on large collections.
Why you can't remove during a for-each
for (String s : list) {
if (s.isEmpty()) list.remove(s); // β ConcurrentModificationException
}
The iterator tracks a modification count. Changing the collection without going through the iterator (or not using the iterator at all) desyncs that count and triggers the exception.
ListIterator β walk forward and back
var it = list.listIterator();
while (it.hasNext()) {
int i = it.nextIndex();
String s = it.next();
it.set(s.toUpperCase()); // replace in-place
}
// Can also .previous(), .hasPrevious(), .add() while iterating
Fail-fast vs fail-safe
- Fail-fast (
ArrayList,HashMap): detect concurrent modification and throw. - Fail-safe (
CopyOnWriteArrayList,ConcurrentHashMap): iterate over a snapshot β no exception, but you may miss concurrent changes.
Common mistakes
- Modifying during for-each β use
removeIfor an explicit iterator. - Calling
next()withouthasNext()βNoSuchElementException. - Using an iterator after the source collection is gone out of scope β undefined behaviour.
Related
Pillar: Java collections. Siblings: ConcurrentModificationException, for-each.