Назад к вопросам
Middle
151
questionbank

Как в однопоточной программе можно получить исключение ConcurrentModificationException при работе с коллекцией?

Sobes Copilot

Получайте ответы в реальном времени

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

sobes.tech AI

// Пример кода, вызывающего ConcurrentModificationException в однопоточном приложении
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ConcModExample {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        Iterator<String> iterator = list.iterator();

        while (iterator.hasNext()) {
            String element = iterator.next();
            if (element.equals("B")) {
                // Попытка изменить коллекцию напрямую во время итерации,
                // выполняемой с помощью итератора.
                // Это вызывает исключение ConcurrentModificationException.
                list.remove(element);
            }
        }
    }
}

ConcurrentModificationExceptionможет возникнуть в однопоточной программе при попытке изменения коллекции во время ее обхода итератором, созданным до этого изменения. Итераторы в коллекционных структурах Java (таких как ArrayList, HashSet, HashMap) используют так называемый "fail-fast" механизм.

Факт возникновения исключения объясняется следующим образом:

  1. При создании итератора коллекция запоминает свой внутренний счетчик модификаций (modCount).
  2. Каждый раз при вызове методов итератора (next(), hasNext(), remove()) происходит проверка, совпадает ли текущий счетчик модификаций коллекции с тем, который был при создании итератора.
  3. Если счетчик изменился с момента создания итератора, возникает ConcurrentModificationException. Это означает, что коллекция была изменена другим способом (например, через прямой вызов методов add(), remove() самой коллекции) во время активного использования итератора.

Исключение указывает на потенциальную проблему согласованности данных при итерации и служит для предотвращения непредсказуемого поведения программы. Чтобы избежать этого, изменения коллекции во время итерации следует производить только через методы самого итератора (iterator.remove()), если они поддерживаются данной коллекцией.