delete - Llamando a remove in foreach loop en Java




remove object list java (8)

En Java, ¿es legal llamar a eliminar en una colección cuando se recorre la colección utilizando un bucle foreach? Por ejemplo:

List<String> names = ....
for (String name : names) {
   // Do something
   names.remove(name).
}

Como anexo, ¿es legal eliminar elementos que aún no se han repetido? Por ejemplo,

//Assume that the names list as duplicate entries
List<String> names = ....
for (String name : names) {
    // Do something
    while (names.remove(name));
}

  1. Intente esto 2. y cambie la condición a "INVIERNO" y se preguntará:
public static void main(String[] args) {
  Season.add("Frühling");
  Season.add("Sommer");
  Season.add("Herbst");
  Season.add("WINTER");
  for (String s : Season) {
   if(!s.equals("Sommer")) {
    System.out.println(s);
    continue;
   }
   Season.remove("Frühling");
  }
 }

Aquellos que dicen que no puede eliminar de forma segura un elemento de una colección, excepto que a través del Iterador no son del todo correctos, puede hacerlo de forma segura utilizando una de las colecciones concurrentes, como ConcurrentHashMap.


El diseño java del "bucle mejorado" fue para no exponer el iterador al código, pero la única forma de eliminar un elemento de manera segura es acceder al iterador. Así que en este caso tienes que hacerlo de la vieja escuela:

 for(Iterator<String> i = names.iterator(); i.hasNext();) {
       String name = i.next();
       //Do Something
       i.remove();
 }

Si en el código real el bucle for mejorado realmente vale la pena, entonces podría agregar los elementos a una colección temporal y llamar a removeAll en la lista después del bucle.

EDITAR (volver a agregar): No, cambiar la lista de cualquier manera fuera del método iterator.remove () mientras se realiza la iteración causará problemas. La única forma de evitar esto es usar un CopyOnWriteArrayList, pero realmente está destinado a problemas de concurrencia.

La forma más barata (en términos de líneas de código) de eliminar duplicados es volcar la lista en un LinkedHashSet (y luego volver a la lista si es necesario). Esto conserva el orden de inserción al eliminar duplicados.


Es mejor usar un iterador cuando desea eliminar un elemento de una lista

porque el código fuente de eliminar es

if (numMoved > 0)
    System.arraycopy(elementData, index+1, elementData, index,
             numMoved);
elementData[--size] = null;

por lo tanto, si elimina un elemento de la lista, la lista se reestructurará, se cambiará el índice del otro elemento, esto puede resultar en algo que usted desea que suceda.


No sabía sobre los iteradores, sin embargo, esto es lo que estaba haciendo hasta hoy para eliminar elementos de una lista dentro de un bucle:

List<String> names = .... 
for (i=names.size()-1;i>=0;i--) {    
    // Do something    
    names.remove(i);
} 

Esto siempre funciona y podría usarse en otros idiomas o estructuras que no admitan iteradores.


Para eliminar de forma segura de una colección mientras se itera sobre ella, debe utilizar un iterador.

Por ejemplo:

List<String> names = ....
Iterator<String> i = names.iterator();
while (i.hasNext()) {
   String s = i.next(); // must be called before you can call i.remove()
   // Do something
   i.remove();
}

De la documentación de Java :

Los iteradores devueltos por el iterador de esta clase y los métodos listIterator son a prueba de fallas: si la lista se modifica estructuralmente en cualquier momento después de que se crea el iterador, de cualquier manera, excepto a través de los propios métodos eliminar o agregar del iterador, el iterador emitirá una excepción ConcurrentModification. Por lo tanto, ante una modificación concurrente, el iterador falla de manera rápida y limpia, en lugar de arriesgarse a comportamientos arbitrarios y no deterministas en un momento indeterminado en el futuro.

Quizás lo que no está claro para muchos novatos es el hecho de que la iteración sobre una lista usando las construcciones for / foreach crea implícitamente un iterador que es necesariamente inaccesible. Esta información se puede encontrar here


Utilizar

.remove () de Interator o

Utilizar

CopyOnWriteArrayList


for (String name : new ArrayList<String>(names)) {
    // Do something
    names.remove(nameToRemove);
}

Clona los names la lista y repite la secuencia mientras elimina de la lista original. Un poco más limpio que la respuesta superior.







foreach