¿Cómo lanza un iterador ConcurrentModificationException al agregar?

¿Cómo Iterator lanzar ConcurrentModificationException cuando agregamos algún objeto después del nodo actual o eliminamos algún objeto después del nodo actual. Lo hace Iterator mantener una copia o referencia a la colección subyacente?

preguntado el 12 de junio de 12 a las 16:06

5 Respuestas

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

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

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

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

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

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 or haz tu propia pregunta.