2009-12-17 2 views
34
for (String fruit : list) 
    { 
     if("banane".equals(fruit)) 
      list.remove(fruit); 
     System.out.println(fruit); 
    } 

Здесь цикл с инструкцией по удалению. Во время выполнения я получаю некоторые ConcurrentModificationException, ниже консольного вывода:петля на список с удалением

Exception in thread "main" java.util.ConcurrentModificationException 
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449) 
at java.util.AbstractList$Itr.next(AbstractList.java:420) 
at Boucle.main(Boucle.java:14) 
abricot 
banane 

Вопрос: Как удалить какой-либо элемент с петлей?

ответ

76

Вам нужно использовать итератор напрямую и удалить элемент через этот итератор.

for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) { 
    String fruit = iterator.next(); 
    if ("banane".equals(fruit)) { 
     iterator.remove(); 
    } 
    System.out.println(fruit); 
} 
+0

Для того, кто признает себя: не использовать для дополнительных с индексом и list.size() !! Я хотел изменить код с помощью цикла foreach, и это не было правильным совпадением. Твоя единственная. – enguerran

+1

просто измените 'it.hasNext()' на 'iterator.hasNext()' и это прекрасно! (очевидно .... но кто знает ....) –

4

Используйте цикл for и обведите коллекцию в обратном порядке. (Это значит, начните с последнего элемента и зациклируйте на первый элемент. Поступая таким образом, вы не получите проблем с индексами, которые меняются из-за удаления элементов из коллекции.

Вы получаете исключение из пример, который вы размещаете, потому что список, по которому вашим итераторов итерации, изменился, что означает, что итератор становится недействительным.

+0

звучит опасно. Как насчет двусвязного списка и тому подобного, где память не соприкасается? Я не знаю, имеют ли списки и т. Д. «Индекс» в Java, или как «итератор» реализован, но если это похоже на C++, я был бы удивлен, если бы ваш подход работал с чем угодно, кроме «ArrayList». –

4
for(Iterator<String> iter = list.iterator(); iter.hasNext();) 
{ 
    String fruit = iter.next(); 
    if("banana".equals(fruit)) 
     iter.remove(); 
    System.out.println(fruit); 
} 
6

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

List<String> toRemove = new ArrayList<String>(); 
for (String fruit : list) { 
    if ("banane".equals(fruit)) 
     toRemove.add(fruit); 
    System.out.println(fruit); 
} 
for (String fruit : toRemove) { 
    list.remove(fruit); 
} 

Помните, я не рекомендую это, это просто альтернатива. :)

+1

Ваше решение слишком подробно – enguerran

+2

Да, это так. Именно поэтому я бы использовал решение на основе «Итератора» - вот что я написал. – Bombe

+0

Существует не один способ сделать это, но большинство из этих способов неверны;) – Jorn

1

Похоже на то, что предложил Бомбе, но в меньшем количестве строк кода, повторяя копию списка, но удаляя из исходного списка;

List<String> temp = new ArrayList<String>(list); 
for (String fruit : temp) 
{ 
    if("banane".equals(fruit)) 
     list.remove(fruit); 
    System.out.println(fruit); 
} 

Лично я считаю, что это выглядит лучше, чем итерация.

+0

Я думаю, что читать легче – enguerran

+0

Я бы сказал, что это ошибка .. имея 2 списка, где нам не нужна вторая. Просто мои 2центы. – cheekoo

+0

@cheekoo, я вижу, как он будет использовать ненужную память, но я не вижу, как компетентный разработчик вводит ошибки с помощью этого метода. –

10

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

for (int i = list.size() - 1; i>=0; i--) { 
    String fruit = list.get(i); 
    System.out.println(fruit); 

    if ("banane".equals(fruit)) { 
     list.remove(fruit); 
    } 
} 
1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); 
Iterator<String> iter = list.iterator(); 
while (iter.hasNext()) { 
    String s = iter.next(); 

    if (s.equals("a")) { 
     iter.remove(); 
    } 
} 

лучший подход ..

Смежные вопросы