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

Aquí un bucle con instrucciones de quitar. En tiempo de ejecución, consigo algunos ConcurrentModificationException, por debajo de la salida de la consola:bucle en la lista con eliminar

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 

Pregunta: ¿Cómo eliminar algún elemento con un bucle?

Respuesta

76

Necesita usar el iterador directamente y eliminar el elemento a través de ese iterador.

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

para el que va a reconocerse a sí mismo: no use para con el índice gradual y list.size() !! Quería cambiar el código con un bucle Foreach y no era la solución correcta. El tuyo es el elegido. – enguerran

+1

simplemente cambie 'it.hasNext()' a 'iterator.hasNext()' ¡y es perfecto! (obvio ... pero quién sabe ...) –

4

Utilice un bucle for, y recorra la colección en orden inverso. (Esto quiere decir, comenzar con el último elemento, y el bucle al primer elemento. Al hacer esto, usted no conseguirá los problemas de los índices que cambian debido a la eliminación de los elementos de la colección.

Se obtiene la excepción el ejemplo que publique, porque la lista sobre la cual sus iteración iterador, ha cambiado, lo que significa que el iterador no es válida.

+0

suena peligroso. ¿Qué hay de la lista doblemente vinculada y similares, donde la memoria no es contigua? No sé si lists y otros tienen 'index' en Java, o cómo' iterator' está implementado, pero si es como C++, me sorprendería si su enfoque ha funcionado con cualquier cosa, excepto '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

Además de utilizar el Iterator directamente (que recomiendo) también se puede almacenar elementos que desea eliminar en una lista diferente.

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

Eso sí, no lo recomiendo, es solo una alternativa. :)

+1

Su solución es demasiado prolija – enguerran

+2

Sí, lo es. Por eso usaría la solución basada en 'Iterator', que es lo que he escrito. – Bombe

+0

Hay más de una forma de hacerlo, pero la mayoría de esas formas son incorrectas;) – Jorn

1

Similar a lo que sugirió Bombe, pero en menos líneas de código al iterar en la lista, pero eliminando de la lista original;

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

Personalmente, creo que esto se ve mejor que iterar con un iterador.

+0

Creo que es más fácil de leer – enguerran

+0

Diría que esto es propenso a errores .. teniendo 2 listas donde no necesitamos el segundo. Solo mis 2cents. – cheekoo

+0

@cheekoo, puedo ver cómo usaría memoria innecesaria, pero no veo cómo un desarrollador competente podría introducir errores usando este método. –

10

Esto parece un poco complicado, ¿por qué no hacer un ciclo normal? Creo que se ve más limpio y no lanzará este error. Solo defiéndeme si eliminas algo. al menos el mío funciona, de todos modos. Ese tipo de bucles automáticos son más para la conveniencia de codificación, pensé, así que si no son convenientes, entonces simplemente no los use.

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

es el mejor enfoque ..

Cuestiones relacionadas