Итераторы, возвращаемые методами iterator и ListIterator этого класса, быстродействующие: если список структурно изменен в любое время после создания итератора любым способом, кроме как с помощью собственных методов remove или add итератора, итератор выдаст исключение ConcurrentModificationException .
Эта проверка выполняется в next() методе итератора (как вы можете видеть по stacktrace). Но мы достигнем next() метода только в том случае, если hasNext() выдано значение true , которое вызывается for each, чтобы проверить, соблюдена ли граница. В вашем методе remove, когда hasNext() проверяет, нужно ли ему возвращать другой элемент, он увидит, что он вернул два элемента, и теперь, после удаления одного элемента, список содержит только два элемента. Итак, все отлично, и мы закончили с итерацией. Проверка одновременных изменений не происходит, поскольку это выполняется в next() методе, который никогда не вызывается.
Далее мы переходим ко второму циклу. После удаления второго числа метод hasNext снова проверит, может ли вернуть больше значений. Он уже вернул два значения, но список теперь содержит только одно. Но приведенный здесь код:
1 != 2, поэтому мы переходим к next() методу, который теперь понимает, что кто-то возился со списком, и запускает исключение.
Надеюсь, это прояснит ваш вопрос.
Краткие сведения
List.remove() не будет выдавать ошибку ConcurrentModificationException при удалении предпоследнего элемента из списка.
Ответ 2
Один из способов справиться с этим - удалить что-либо из копии Collection (не саму коллекцию), если применимо. Clone исходную коллекцию нужно скопировать через Constructor.
Это исключение может быть вызвано методами, которые обнаружили одновременную модификацию объекта, когда такая модификация недопустима.
Для вашего конкретного случая, во-первых, я не думаю, что final это правильный путь, учитывая, что вы намерены изменить предыдущее объявление списка
privatestaticfinal List<Integer> integerList;
Также рассмотрите возможность изменения копии вместо исходного списка.
Метод forward / iterator не работает при удалении элементов. Вы можете удалить элемент без ошибок, но вы получите ошибку времени выполнения при попытке получить доступ к удаленным элементам. Вы не можете использовать итератор, потому что, как показывает pushy, это вызовет исключение ConcurrentModificationException , поэтому вместо этого используйте обычный цикл for , но выполните его в обратном порядке.
//Item to remove Integerremove= Integer.valueOf(3);
Решение:
Пройдите по массиву в обратном порядке, если вы собираетесь удалить элемент списка. Просто просматривая список в обратном порядке, вы избегаете посещения элемента, который был удален, что удаляет исключение.
//To remove items from the list, start from the end and go backwards through the arrayList //This way if we remove one from the beginning as we go through, then we will avoid getting a runtime error //for java.lang.IndexOutOfBoundsException or java.util.ConcurrentModificationException as when we used the iterator for (int i=size-1; i> -1; i--) { if (integerList.get(i).equals(remove) ) { integerList.remove(i); } }
Ответ 4
Этот фрагмент всегда будет вызывать исключение ConcurrentModificationException.
Правило гласит: "Вы не имеете права изменять (добавлять или удалять элементы из списка) при выполнении итерации по нему с помощью итератора (что происходит, когда вы используете цикл for-each)".
JavaDocs:
Итераторы, возвращаемые методами iterator и ListIterator этого класса, быстродействующие: если список структурно изменен в любое время после создания итератора любым способом, кроме как с помощью собственных методов remove или add итератора, итератор выдаст исключение ConcurrentModificationException .
Следовательно, если вы хотите изменить список (или любую коллекцию в целом), используйте iterator , потому что тогда он знает об изменениях и, следовательно, они будут обработаны должным образом.