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

Ici une boucle avec instruction remove. Au moment de l'exécution, je reçois une ConcurrentModificationException, en dessous de la sortie de la console:boucle sur liste avec suppression

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 

Question: Comment faire pour supprimer un élément avec une boucle?

Répondre

76

Vous devez utiliser directement l'itérateur et supprimer l'élément via cet itérateur.

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

Pour celui qui se reconnaîtra: ne pas utiliser pour avec un indice supplémentaire et list.size() !! Je voulais changer le code avec une boucle foreach et ce n'était pas la bonne solution. Le tien est celui. – enguerran

+1

il suffit de changer 'it.hasNext()' en 'iterator.hasNext()' et c'est parfait! (évident .... mais qui sait ....) –

4

Utilisez une boucle for et faites une boucle sur la collection dans l'ordre inverse. (Cela veut dire, commencer par le dernier élément, et la boucle au premier élément. Ce faisant, vous ne serez pas avoir des problèmes par les indices qui changent en raison de la suppression d'éléments de la collection.

Vous obtenez l'exception l'exemple que vous publiez, parce que la liste sur laquelle votre itère iterator, a changé, ce qui signifie que le iterator devient invalide.

+0

semble dangereux. Qu'en est-il de la liste doublement liée et autres, où la mémoire n'est pas contiguë? Je ne sais pas si lists et al ont 'index' en Java, ou comment' iterator' est implémenté, mais si c'est comme C++, je serais surpris si votre approche fonctionnait avec n'importe quoi sauf '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

En plus d'utiliser la Iterator directement (que je recommande), vous pouvez également stocker éléments que vous souhaitez supprimer dans une liste différente:

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); 
} 

Rappelez-vous, je ne le recommande pas, c'est juste une alternative. :)

+1

Votre solution est trop verbeuse – enguerran

+2

Oui, c'est le cas. C'est pourquoi j'utiliserais la solution "Iterator" - c'est ce que j'ai écrit. – Bombe

+0

Il y a plus d'une façon de le faire, mais la plupart de ces façons sont fausses;) – Jorn

1

Similaire à ce que Bombe a suggéré, mais en moins de lignes de code en itérant sur la copie de liste, mais en supprimant de la liste originale; Personnellement, je pense que cela semble plus agréable que d'itérer avec un itérateur.

+0

Je pense qu'il est plus facile de lire – enguerran

+0

Je dirais que c'est sujettes aux bugs .. ayant 2 listes où nous n'avons pas besoin de la seconde. Juste mes 2cents. – cheekoo

+0

@cheekoo, je peux voir comment il utiliserait la mémoire inutile, mais je ne vois pas comment un développeur compétent pourrait introduire des bugs en utilisant cette méthode. –

10

Cela semble un peu compliqué, pourquoi ne pas faire une boucle normale? Je pense que cela semble plus propre et ne va pas jeter cette erreur. Décimale juste si tu enlèves quelque chose. Au moins, la mine fonctionne, de toute façon. Ce genre d'auto-boucles sont plus pour la commodité de codage, je pensais, donc si elles ne sont pas pratiques, alors ne les utilisez pas.

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(); 
    } 
} 

est la meilleure approche ..

Questions connexes