Как безопасно удалять элементы коллекции во время итерации и избежать ConcurrentModificationException?

Контекст: Java, коллекции и итерация ConcurrentModificationException появляется, если структурно изменить коллекцию не через используемый итератор Для удаления во время обхода применяйте Iterator.remove() Ещё один…

Короткий ответ

Что ответить на собеседовании

Контекст: Java, коллекции и итерация ConcurrentModificationException появляется, если структурно изменить коллекцию не через используемый итератор Для удаления во время обхода применяйте Iterator.remove() Ещё один вариант — CopyOnWriteArrayList, потокобезопасная коллекция, создающая копию элементов Можно сначала поместить элементы для удаления в отдельный список, а затем удалить их после завершения итерации В многопоточном коде используют ConcurrentHashMap либо синхронизируют доступ Итог: удаляйте элементы через итератор или подготовьте их заранее, не изменяя коллекцию напрямую внутри цикла

Подробный разбор

Ответ с пояснениями

Как безопасно удалять элементы коллекции во время итерации и избежать ConcurrentModificationException?

  • Контекст: Java, коллекции и итерация
  • ConcurrentModificationException появляется, если структурно изменить коллекцию не через используемый итератор
  • Для удаления во время обхода применяйте Iterator.remove()
  • Ещё один вариант — CopyOnWriteArrayList, потокобезопасная коллекция, создающая копию элементов
  • Можно сначала поместить элементы для удаления в отдельный список, а затем удалить их после завершения итерации
  • В многопоточном коде используют ConcurrentHashMap либо синхронизируют доступ
  • Итог: удаляйте элементы через итератор или подготовьте их заранее, не изменяя коллекцию напрямую внутри цикла

Такой способ сохраняет корректность итерации и предотвращает исключения.

Подробный ответ

Основной ответ

ConcurrentModificationException возникает при изменении коллекции, например при удалении элемента во время обхода стандартным итератором, если не использовать предусмотренные для этого операции. Безопасный вариант — вызвать Iterator.remove() либо выбрать структуру, допускающую корректные изменения во время итерации, например коллекции из java.util.concurrent.

Ключевые моменты

  • Iterator.remove() — штатный способ удалить текущий элемент без исключения. Метод согласован с итератором и правильно обновляет внутренние счётчики модификаций коллекции.
  • Использование CopyOnWriteArrayList или других потокобезопасных коллекций из пакета java.util.concurrent позволяет изменять данные во время итерации без ConcurrentModificationException. При этом необходимо учитывать накладные расходы, в частности копирование при каждой модификации.
  • Создание промежуточных списков — ещё один вариант: сначала собрать элементы, предназначенные для удаления, а после завершения обхода удалить их за пределами цикла. Метод прост, но менее эффективен.

Практический контекст

В прикладном коде, например при фильтрации или очистке кэша, для классических коллекций ArrayList и HashSet в однопоточной либо контролируемой среде обычно выбирают Iterator с remove(). В многопоточном приложении предпочтительнее CopyOnWriteArrayList или ConcurrentHashMap: они помогают избежать блокировок и исключений. В результате код остаётся стабильным и понятным, без неожиданных ошибок во время выполнения.

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку