Что такое fail-fast поведение в Java коллекциях? Приведите пример.

«Что такое fail-fast поведение в Java коллекциях? Приведите пример.» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Fail-fast — это поведение итератора коллекции, при котором он немедленно выбрасывает исключение ConcurrentModificationException, если обнаруживает структурное изменение коллекции (добавление, удаление элементов) любым способом, кроме собственных методов итератора, во время итерации.

Цель: Предотвратить неопределенное поведение и помочь быстро найти ошибку синхронизации в коде.

Пример, вызывающий исключение:

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

for (String item : list) { // Неявно используется Iterator<String>
    if (item.equals("B")) {
        list.remove(item); // Модификация коллекции НЕ через итератор!
        // Выбросит ConcurrentModificationException
    }
}

Как работает: Итератор хранит внутренний счетчик модификаций коллекции (modCount). При каждой операции итерации (hasNext(), next()) он сравнивает сохраненное значение с текущим modCount. Если они различаются — бросается исключение.

Корректные способы модификации во время итерации:

  1. Использовать методы самого итератора:
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        String item = iterator.next();
        if (item.equals("B")) {
            iterator.remove(); // Безопасное удаление
        }
    }
  2. Использовать fail-safe коллекции из пакета java.util.concurrent (например, CopyOnWriteArrayList, ConcurrentHashMap). Они работают с копией данных и не бросают это исключение.

Fail-fast коллекции: ArrayList, HashMap, HashSet, Vector (и его Enumeration). Важно: Fail-fast не гарантирует обнаружение всех асинхронных модификаций, это механизм для отладки, а не для контроля потокобезопасности.