¿Cómo lanza un iterador ConcurrentModificationException al agregar?
Frecuentes
Visto 5,448 veces
5 Respuestas
5
El iterador mantiene una referencia a la colección subyacente. Si agrega o elimina un elemento, el iterador puede quedar en un índice imposible, o la colección puede cambiar "por debajo" del iterador.
Por lo tanto, en lugar de permitir que el iterador se corrompa sin avisarle, la mayoría de las colecciones tienen la cortesía de lanzar una ConcurrentModificationException cuando intenta modificar la colección durante la iteración, para que no termine con iteradores dañados de forma impredecible.
Respondido el 12 de junio de 12 a las 16:06
2
Por contrato, no se le permite modificar la colección mientras itera sobre ella (excepto mediante el uso de Iterator.remove()
y otros).
En lugar de fallar al azar cuando haces esto, la colección es lo suficientemente agradable como para realizar un seguimiento de cuántas veces se ha modificado y arrojar ConcurrentModificationException
cuando detecta modificaciones concurrentes.
Respondido el 12 de junio de 12 a las 16:06
1
Esa ConcurrentModificationException es probablemente tu amiga y deberías aprender a vivir con ella. Sin embargo, solo para completar:
Hay colecciones que no son de Oracle que no lanzan ConcurrentModificationException. Son más rápidos (porque no pierden tiempo comprobando) y, obviamente, más flexibles, pero requieren un mayor cuidado a la hora de utilizarlos.
Oracle tiene cuatro (en el último recuento) clases "concurrentes" que tampoco lo lanzan en java.util.concurrent (ConcurrentHashMap, ConcurrentLinkedQueue, ConcurrentSkipListMap y ConcurrentSkipListSet). Son marginalmente más lentos que sus equivalentes no concurrentes, pero son seguros para subprocesos. y ellos no bloquees. No codificarán sus datos sin importar qué lo haces, pero no se detendrán de revolverlo.
Respondido el 13 de junio de 12 a las 21:06
1
Para eliminar, puede usar iterator.remove(), de la siguiente manera:
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Object object = iterator.next();
/* ... */
if (condition) {
iterator.remove();
}
Para agregar, puede reemplazar Iterator simple por ListIterator, de la siguiente manera
ListIterator<Object> iterator = list.listIterator();
iterator.add(new Object());
Respondido 08 ago 12, 05:08
0
Por supuesto, un iterador tiene un enlace a la colección subyacente, esto evita la copia. Si observa, por ejemplo, el código fuente del iterador ArrayList (ListItr), verá que en su mayoría tiene un enlace a la lista y un cursor.
Por lo tanto, no comparta un iterador entre subprocesos y no modifique una colección en la que está iterando.
Respondido el 12 de junio de 12 a las 16:06
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas java iterator or haz tu propia pregunta.
el iterador no tiene método de agregar, solo tiene 3 métodos siguiente, siguiente, eliminar. - banjara
Debería usar ListIterator no solo el tipo Iterator - Moesio