middle
Как избежать ConcurrentModificationException во время перебора коллекции
ConcurrentModificationException можно избежать несколькими способами, выбор зависит от того, однопоточный или многопоточный контекст.
Для однопоточного кода:
- Использовать
iterator.remove()вместоcollection.remove()— итератор корректно синхронизирует счетчик модификаций. - Собрать элементы для удаления в отдельную коллекцию и вызвать
removeAll()после завершения итерации. - Использовать
removeIf(Predicate)(Java 8+), который внутри безопасно удаляет элементы. - Преобразовать коллекцию в массив (
toArray()) и перебирать массив.
Для многопоточного кода:
- Использовать
CopyOnWriteArrayListилиCopyOnWriteArraySet— они создают копию при каждой модификации. - Использовать
ConcurrentHashMapвместо HashMap — итераторы с weakly consistent семантикой. - Оборачивать итерацию в
synchronized-блок (но это снижает производительность).
На собеседовании: начните с iterator.remove() и removeIf() — это самые практичные подходы. Затем упомяните concurrent-коллекции для многопоточного контекста.