Примечание: я знаю о Iterator#remove()
методе.
В следующем примере кода, я не понимаю , почему List.remove
в main
метод бросает ConcurrentModificationException
, но не в remove
методе.
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
java
list
concurrentmodification
foreach
Беш Гурунг
источник
источник
Iterator#remove()
. Почему ты так делаешь?ConcurrentModificationException
а другой нет.return;
в цикл.Ответы:
И вот почему: как говорится в Javadoc:
Эта проверка выполняется в
next()
методе итератора (как вы можете видеть по трассировке стека). Но мы дойдем доnext()
метода только в том случае, еслиhasNext()
доставлено значение true, что и вызывается для каждого, чтобы проверить, встречается ли граница. В вашем методе remove приhasNext()
проверке необходимости возврата другого элемента он увидит, что он возвратил два элемента, и теперь после удаления одного элемента список содержит только два элемента. Так что все хорошо, и мы закончили с итерацией. Проверка на одновременные изменения не происходит, поскольку это делается вnext()
методе, который никогда не вызывается.Далее мы перейдем ко второму циклу. После того, как мы удалим второе число, метод hasNext снова проверит, может ли вернуть больше значений. Он уже вернул два значения, но теперь список содержит только одно значение. Но код здесь:
1! = 2, поэтому мы переходим к
next()
методу, который теперь понимает, что кто-то возился со списком, и вызывает исключение.Надеюсь, это прояснит ваш вопрос.
Резюме
List.remove()
не выбрасывает,ConcurrentModificationException
когда удаляет второй последний элемент из списка.источник
Один из способов справиться с этим - удалить что-либо из копии
Collection
(не самой Коллекции), если это применимо.Clone
оригинальная коллекция это сделать копию черезConstructor
.Для вашего конкретного случая, во-первых, я не думаю, что
final
это способ пойти, учитывая, что вы намерены изменить список после объявленияТакже рассмотрите возможность изменения копии вместо исходного списка.
источник
Метод forward / iterator не работает при удалении элементов. Вы можете удалить элемент без ошибок, но вы получите ошибку времени выполнения при попытке доступа к удаленным элементам. Вы не можете использовать итератор, потому что, как показывает настойчивость, он вызовет исключение ConcurrentModificationException, поэтому вместо него используйте регулярный цикл for, но переходите назад.
Решение:
Обходите массив в обратном порядке, если вы собираетесь удалить элемент списка. Проходя назад по списку, вы избегаете посещения элемента, который был удален, что исключает исключение.
источник
Этот фрагмент всегда вызывает исключение ConcurrentModificationException.
Правило гласит: «Вы не можете изменять (добавлять или удалять элементы из списка) во время итерации по нему с помощью итератора (что происходит при использовании цикла for-each)».
JavaDocs:
Итераторы, возвращаемые методами итератора этого класса и метода listIterator, работают без сбоев: если список структурно изменяется в любое время после создания итератора, любым способом, кроме использования собственных методов удаления или добавления итератора, итератор создает исключение ConcurrentModificationException.
Следовательно, если вы хотите изменить список (или любую коллекцию в целом), используйте итератор, потому что тогда он знает об изменениях, и, следовательно, они будут обработаны правильно.
Надеюсь это поможет.
источник
У меня была та же проблема, но в случае, когда я добавлял элемент en в итеративный список. Я сделал это так
Теперь все идет хорошо, потому что вы не создаете итератор для своего списка, вы выполняете его «вручную». И условие
i < integerList.size()
никогда не обманет вас, потому что, когда вы удаляете / добавляете что-то в список, размер списка уменьшается / увеличивается.Надеюсь, это поможет, для меня это было решением.
источник
Если вы используете коллекции копирования при записи, это будет работать; однако, когда вы используете list.iterator (), возвращаемый Iterator всегда будет ссылаться на коллекцию элементов, как это было, когда (как показано ниже) вызывался list.iterator (), даже если другой поток изменяет коллекцию. Любые мутирующие методы, вызываемые для итератора на основе копирования при записи или ListIterator (например, для добавления, установки или удаления), будут генерировать исключение UnsupportedOperationException.
источник
Это нормально работает на Java 1.6
~% javac RemoveListElementDemo.java
~% java RemoveListElementDemo
~% cat RemoveListElementDemo.java
~%
источник
В моем случае я сделал это так:
источник
Замените Iterator
for each
на,for loop
чтобы решить.И причина в том, что:
- Ссылка на Java Документы.
источник
Проверьте ваш код, человек ....
В основном методе вы пытаетесь удалить 4-й элемент, которого нет, и, следовательно, ошибка. В методе remove () вы пытаетесь удалить третий элемент, который существует и, следовательно, не содержит ошибок.
источник
2
и3
не индексы для списка, а элементы. Обе логики удаления проверяют наequals
соответствие элементам списка, а не индексу элементов. Кроме того, если бы это было связано с индексом, этоIndexOutOfBoundsException
не такConcurrentModificationException
.