Expired sessions removed mid-iteration
A easy Java puzzle in the modifying while iterating family. One line below contains a real bug. Try to spot it first, then read why it fails and how to fix it.
Highlighted: line 9. Play this one as a puzzle without the answer.
What is wrong
Removing from the map while iterating its entry set invalidates the iterator, so the next step throws ConcurrentModificationException. Only the iterator itself may remove during iteration.
The fix
How to avoid it next time
Use entrySet().removeIf or keySet().removeIf for map clean-up.
Want the background? Read Map idioms: merge, compute, entrySet in the Java concepts library.
About modifying while iterating
Collections detect structural changes made during iteration and throw ConcurrentModificationException, but only some of the time, and not at all for certain patterns. Removing in a loop is a classic way to skip elements or crash.
In code review: Any call to add or remove on the collection being looped over deserves suspicion. Use Iterator.remove, removeIf, or build a new collection.
More puzzles in this family
Frequently asked questions
What is the bug in "Expired sessions removed mid-iteration"?
Removing from the map while iterating its entry set invalidates the iterator, so the next step throws ConcurrentModificationException. Only the iterator itself may remove during iteration. The faulty line is line 9: if (e.getValue() < now) expiry.remove(e.getKey());
How do I fix it?
Replace it with: expiry.entrySet().removeIf(e -> e.getValue() < now);. Use entrySet().removeIf or keySet().removeIf for map clean-up.
How do I catch modifying while iterating in code review?
Any call to add or remove on the collection being looped over deserves suspicion. Use Iterator.remove, removeIf, or build a new collection.
Is there a new puzzle every day?
Yes. The daily Spot the Bug puzzle picks one of these snippets for each UTC day, with the difficulty set by the weekday. Your streak is stored only in your browser.