Java.Collections.How to avoid ConcurrentModificationException when iterating over a collection?

💥 Why does ConcurrentModificationException happen?

It occurs when:

  • You’re iterating over a collection (using an Iterator or for-each loop)
  • And the collection is structurally modified outside the iterator during iteration

✅ How to Avoid It — 5 Safe Strategies

✅ 1. Use the Iterator’s remove() method

Only use the iterator itself to remove elements — never the collection.

List<String> list = new ArrayList<>(List.of("A", "B", "C"));
Iterator<String> it = list.iterator();

while (it.hasNext()) {
    if (it.next().equals("B")) {
        it.remove(); // ✅ Safe — handled by iterator
    }
}

❌ Don’t do this:

for (String s : list) {
    if (s.equals("B")) {
        list.remove(s); // ❌ ConcurrentModificationException
    }
}

✅ 2. Use a ListIterator if you need to add(), set(), or remove()

List<String> list = new ArrayList<>(List.of("A", "B", "C"));
ListIterator<String> lit = list.listIterator();

while (lit.hasNext()) {
    String val = lit.next();
    if (val.equals("B")) {
        lit.set("Beta");   // ✅ Replaces "B"
        lit.add("Bravo");  // ✅ Adds after "Beta"
    }
}

✅ 3. Iterate over a copy of the collection

If you need to modify the collection while iterating — don’t iterate over the original.

List<String> list = new ArrayList<>(List.of("A", "B", "C"));
for (String s : new ArrayList<>(list)) {
    if (s.equals("B")) {
        list.remove(s); // ✅ Safe, because we're iterating over a copy
    }
}

Works well for read-modify scenarios where performance isn’t critical.

✅ 4. Use Concurrent Collections (fail-safe)

In multithreaded environments, use classes from java.util.concurrent, such as:

  • CopyOnWriteArrayList
  • ConcurrentHashMap
  • ConcurrentSkipListSet

These do not throw ConcurrentModificationException, even when modified during iteration.

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(List.of("A", "B", "C"));

for (String s : list) {
    if (s.equals("B")) {
        list.remove(s); // ✅ Safe in CopyOnWriteArrayList
    }
}

⚠️ Trade-off: expensive for frequent writes (since copies are made on every modification).

✅ 5. Use streams or filters instead of manual removal

List<String> list = new ArrayList<>(List.of("A", "B", "C"));
list = list.stream()
           .filter(s -> !s.equals("B")) // keep everything except "B"
           .collect(Collectors.toList()); // ✅ Safe

Cleaner, functional style — often better for batch filtering.

🧠 Summary Table

StrategySafe?Notes
iterator.remove()Standard safe method during iteration
Modifying collection directlyCauses exception during iteration
Iterating over a copySafe and easy, may use more memory
Using ListIteratorAllows bidirectional traversal and modification
Using concurrent collectionsThread-safe, no exception, but slower on writes
Using stream/filterFunctional, clean, not in-place
This entry was posted in Без рубрики. Bookmark the permalink.