Вопрос-ответ

Getting a ConcurrentModificationException thrown when removing an element from a java.util.List during list iteration? [duplicate]

Возникает исключение ConcurrentModificationException при удалении элемента из java.util.List во время итерации списка?
@Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}

for(String st:li){
if(st.equalsIgnoreCase("str3"))
li.remove("str3");
}
System.out.println(li);
}

Когда я запускаю этот код, я выдаю ConcurrentModificationException.

Похоже, что когда я удаляю указанный элемент из list, list не знает, что его size изменили.

Мне интересно, является ли это распространенной проблемой с collections и удалением элементов?

Переведено автоматически
Ответ 1

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

Например:

Iterator<String> iter = li.iterator();
while(iter.hasNext()){
if(iter.next().equalsIgnoreCase("str3"))
iter.remove();
}
Ответ 2

Способ Java 8 удалить его из списка без итератора - это:

li.removeIf(<predicate>)

т.е.

List<String> li = new ArrayList<String>();
// ...
li.removeIf(st -> !st.equalsIgnoreCase("str3"));
Ответ 3

Обратите внимание, что это исключение не всегда указывает на то, что объект был одновременно изменен другим потоком. Если один поток выдает последовательность вызовов метода, которая нарушает контракт объекта, объект может выдать это исключение. Например, если поток изменяет коллекцию напрямую во время итерации по коллекции с помощью отказоустойчивого итератора, итератор удалит это исключение


Взято из http://download.oracle.com/javase/1.4.2/docs/api/java/util/ConcurrentModificationException.html

Ответ 4

да, люди сталкиваются с этим - проблема в том, что вы не можете изменять список во время итерации по нему. В прошлом я использовал 2 альтернативы:


  1. Вы можете отслеживать индексы элементов, которые хотите удалить, а затем удалять их после завершения итерации.

  2. Или вы можете скопировать все те, которые хотите сохранить, в новый список по мере итерации, а затем удалить старый список по завершении.

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

В вашем конкретном случае вам даже не нужно выполнять итерацию, так как вы можете просто использовать removeAll . Посмотрите на API здесь . Существуют также отличные методы, такие как retainAll, которые отбрасывают все, чего нет в аргументе. Вы можете использовать методы, подобные remove / retain, всякий раз, когда объекты в списке правильно реализуют equals и hashcode . Если вы не можете полагаться на equals / hashcode для определения равенства между экземплярами в вашем приложении, вам придется выполнить удаление самостоятельно....

java list