Question
What causes java.util.ConcurrentModificationException during JUnit tests and how can it be resolved?
// Sample code that may cause ConcurrentModificationException
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
for (String item : list) {
list.remove(item); // This line causes ConcurrentModificationException
}
Answer
The java.util.ConcurrentModificationException occurs when a collection is modified while it is being iterated over. This is a common issue in JUnit tests when the code under test modifies a collection during iteration, which violates the fail-fast behavior of Java's collection framework.
// Safe removal with iterator
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (shouldRemove(item)) { // Condition to remove item
iterator.remove(); // Safe removal
}
}
Causes
- Modifying a collection (like adding or removing elements) while iterating through it using an iterator or enhanced for-loop.
- Concurrent modifications by multiple threads (though less common in single-threaded JUnit tests).
- Using a collections class that does not support concurrent modification in a multi-threaded test environment.
Solutions
- Use an iterator for safe removal of elements when iterating, allowing the use of the iterator's remove method.
- Copy the collection to a separate list before iterating if modifications are needed during the loop.
- Utilize synchronized collections or concurrent collection classes (like CopyOnWriteArrayList) when working in a multi-threaded environment.
Common Mistakes
Mistake: Altering the collection directly while using an enhanced for-loop.
Solution: Use an iterator and call its remove method to avoid concurrent modification.
Mistake: Assuming that all collections handle concurrent modifications optimally.
Solution: Be mindful of the collection type used; prefer concurrent collections in multi-threaded scenarios.
Helpers
- ConcurrentModificationException
- JUnit tests
- Java exception handling
- Java collections
- Fix ConcurrentModificationException