Исключение одновременной модификации Java не возникает при использовании метода удаления коллекций

Во многих местах я видел, что при удалении элемента из ArrayList во время итерации я должен использовать метод удаления итератора вместо метода удаления коллекций, чтобы избежать исключения одновременной модификации.

Однако приведенный ниже код отлично работает с использованием удаления коллекции Java 1.8 без исключения одновременной модификации. Вы можете видеть, что я не использую здесь итератор для удаления объекта.

List<MyObject> list = new ArrayList<MyObject>();
list.add(new MyObject());
list.add(new MyObject());
list.add(new MyObject());

for (int i=0; i<list.size(); i++) {
        list.remove(i);     
}

person KItis    schedule 24.09.2017    source источник
comment
Исключение параллельной модификации выдается на основе лучших усилий, ваша программа не всегда может ожидать, что оно будет выброшено, когда это произойдет.   -  person Ferrybig    schedule 24.09.2017
comment
Повезло тебе или на самом деле не повезло... решать тебе.   -  person Maroun    schedule 24.09.2017
comment
Как вы думаете, почему вообще выбрасывается ConcurrentModificationException?   -  person Mark Rotteveel    schedule 24.09.2017
comment
Если вам интересно, почему он не делает то, что вы ожидаете, проверьте Javadoc для всех методов, которые вы вызываете.   -  person Andy Turner    schedule 24.09.2017


Ответы (1)


Ваш пример не вызовет исключения. Однако при этом не будут удалены все элементы из списка.

Что он делает на самом деле

  • На первой итерации он удаляет индекс 0; В списке осталось 2 элемента
  • На второй итерации он удаляет индекс 1 (фактически последний элемент); 1 элемент остался
  • Третьей итерации не произойдет, потому что к тому времени list.size() равно 1, что меньше 2.

Сначала я думал, что он выдаст IndexOutOfBoundsException, но тот факт, что list.size() оценивается в начале каждой итерации, гарантирует, что этого не произойдет.

Почему он не выдает ConcurrentModificationException

Потому что вы не используете итератор.

Это исключение возникает, если вы перебираете список с помощью итератора, затем изменяете (например, удаляете) список, и затем пытаетесь продвинуть итератор, например:

Iterator<MyObject> it = list.iterator();
while (it.hasNext()) {
    list.remove(it.next());
}

Как отметил @Ferrybig, даже в этом случае итератор может фактически не вызывать исключение - см. связанный вопрос.

person Jiri Tousek    schedule 24.09.2017