Ответ
Попытка изменить структуру коллекции (добавить или удалить элементы) во время итерации по ней с помощью Iterator или цикла for-each приведет к выбросу ConcurrentModificationException. Это защитный механизм, предотвращающий недетерминированное поведение.
Пример, вызывающий исключение:
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String item : list) {
if (item.equals("B")) {
list.remove(item); // ConcurrentModificationException!
}
}
Безопасные способы изменения коллекции во время обхода:
-
Использование
Iterator.remove(): Позволяет безопасно удалять текущий элемент.Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String item = iterator.next(); if (item.equals("B")) { iterator.remove(); // Корректное удаление } } -
Создание копии коллекции для итерации: Итерируем по копии, а изменяем оригинал.
new ArrayList<>(list).forEach(item -> { if (item.equals("B")) { list.remove(item); // Безопасно, так как итерация по копии } }); -
Использование потокобезопасных коллекций: Например,
CopyOnWriteArrayListсоздает новую копию внутреннего массива при каждой модификации, что позволяет безопасно итерироваться по старой версии.List<String> safeList = new CopyOnWriteArrayList<>(Arrays.asList("A", "B", "C")); for (String item : safeList) { if (item.equals("B")) { safeList.remove(item); // Без исключения } }
Важно: Изменение значения элемента (например, поля объекта в коллекции) через существующую ссылку не вызывает исключения, так как не меняет структуру самой коллекции.