Nota: conozco el Iterator#remove()
método.
En el siguiente ejemplo de código, no entiendo por qué el método List.remove
in main
arroja ConcurrentModificationException
, pero no en el remove
método.
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
java
list
concurrentmodification
foreach
Bhesh Gurung
fuente
fuente
Iterator#remove()
. ¿Por qué lo haces de esta manera?ConcurrentModificationException
y el otro no.return;
en el bucle.Respuestas:
He aquí por qué: como se dice en el Javadoc:
Esta comprobación se realiza en el
next()
método del iterador (como puede ver en el stacktrace). Pero alcanzaremos elnext()
método solo si sehasNext()
entrega verdadero, que es lo que llama cada uno para verificar si se cumple el límite. En su método de eliminación, cuandohasNext()
verifica si necesita devolver otro elemento, verá que devuelve dos elementos, y ahora, después de eliminar un elemento, la lista solo contiene dos elementos. Entonces, todo es color de rosa y hemos terminado con la iteración. La verificación de modificaciones concurrentes no ocurre, ya que esto se hace en elnext()
método que nunca se llama.Luego llegamos al segundo bucle. Después de eliminar el segundo número, el método hasNext verificará nuevamente si puede devolver más valores. Ya ha devuelto dos valores, pero la lista ahora solo contiene uno. Pero el código aquí es:
1! = 2, así que continuamos con el
next()
método, que ahora se da cuenta de que alguien ha estado jugando con la lista y activa la excepción.Espero que aclare tu pregunta.
Resumen
List.remove()
no se lanzaráConcurrentModificationException
cuando elimine el segundo último elemento de la lista.fuente
Una forma de manejarlo es eliminar algo de una copia de
Collection
(no la Colección en sí), si corresponde.Clone
la colección original para hacer una copia a través de aConstructor
.Para su caso específico, en primer lugar, no creo que
final
sea un camino a seguir considerando que tiene la intención de modificar la declaración pasada de la listaTambién considere modificar una copia en lugar de la lista original.
fuente
El método de reenvío / iterador no funciona al eliminar elementos. Puede eliminar el elemento sin error, pero recibirá un error de tiempo de ejecución cuando intente acceder a los elementos eliminados. No puede usar el iterador porque, como muestra Pushy, causará una excepción ConcurrentModificationException, por lo tanto, use un bucle for regular, pero retroceda.
Una solución:
Atraviese la matriz en orden inverso si va a eliminar un elemento de la lista. Simplemente yendo hacia atrás a través de la lista, evita visitar un elemento que se ha eliminado, lo que elimina la excepción.
fuente
Este fragmento siempre arrojará una ConcurrentModificationException.
La regla es "No puede modificar (agregar o eliminar elementos de la lista) mientras itera sobre él usando un iterador (que ocurre cuando usa un ciclo for-each)".
JavaDocs:
Los iteradores devueltos por el iterador de esta clase y los métodos listIterator son rápidos: 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 remove o add del iterador, el iterador arrojará una ConcurrentModificationException.
Por lo tanto, si desea modificar la lista (o cualquier colección en general), use el iterador, porque entonces está al tanto de las modificaciones y, por lo tanto, se manejarán correctamente.
Espero que esto ayude.
fuente
Tuve el mismo problema, pero en caso de que estuviera agregando un elemento en la lista iterada. Lo hice de esta manera
Ahora todo va bien porque no creas ningún iterador sobre tu lista, lo iteras "manualmente". Y condición
i < integerList.size()
nunca te engañará porque cuando eliminas / agregas algo al tamaño de la Lista de la disminución / incremento de la Lista ...Espero que ayude, para mí esa fue la solución.
fuente
Si utiliza colecciones de copia en escritura, funcionará; sin embargo, cuando utiliza list.iterator (), el Iterador devuelto siempre hará referencia a la colección de elementos tal como estaba cuando (como se indica a continuación) se llamó a list.iterator (), incluso si otro subproceso modifica la colección. Cualquier método de mutación invocado en un Iterador basado en copia en escritura o ListIterator (como agregar, establecer o eliminar) arrojará una UnsupportedOperationException.
fuente
Esto funciona bien en Java 1.6
~% javac RemoveListElementDemo.java
~% java RemoveListElementDemo
~% cat RemoveListElementDemo.java
~%
fuente
En mi caso lo hice así:
fuente
Cambia Iterator
for each
afor loop
para resolver.Y la razón es:
- Documentos Java referidos.
fuente
Comprueba tu código hombre ...
En el método principal, está tratando de eliminar el cuarto elemento que no está allí y, por lo tanto, el error. En el método remove (), está tratando de eliminar el tercer elemento que está allí y, por lo tanto, no hay error.
fuente
2
y3
no son índices para la lista, sino elementos. Ambas lógicas de eliminación verificanequals
los elementos de la lista, no el índice de los elementos. Además, si estuviera relacionado con el índice, lo estaríaIndexOutOfBoundsException
, noConcurrentModificationException
.