2012-05-18 11 views
6

Utilizando for(Type x:collection){...}, ¿qué tipos de colecciones ampliamente utilizadas hacen que la eliminación de x sea segura durante la iteración?¿Qué colecciones estándar de Java son eliminables durante la iteración?

¿Y hay un término técnico para esto a tener en cuenta en los JavaDocs?

Aclaración:

que inicialmente sólo preguntó sobre el uso de la sintaxis de cada uno-for(Type x:collection){...}. Sin embargo, una respuesta más completa describiría este estilo Y utilizando un bucle normal basado en iterador donde existen diferencias ... la pregunta es más acerca de qué Colecciones estándar me permiten eliminar elementos durante la iteración, Y cómo realizar la iteración para permitir esto.

+0

¿Quiere decir para cada iteración o iteración de 'Iterator'? – Tharwen

+0

@Tharwen esos son los mismos ... – jjm

+1

@jjm: Para los fines de esta pregunta, son * muy * diferentes. – NPE

Respuesta

5

Una de estas colecciones es CopyOnWriteArrayList. Otras colecciones en el paquete java.util.concurrent comparten esta característica.

El hecho de que sus iteradores nunca arrojen un ConcurrentModificationException es un efecto secundario de la semántica de copia de escritura de esta clase: cada vez que lo modifique, se copiará la matriz subyacente. Esto se hace para permitir el acceso concurrente rápido a listas de lectura frecuente pero rara vez modificadas.

el Javadoc explica así (énfasis mío):

El método de "instantánea" estilo iterador utiliza una referencia al estado de la matriz en el punto que el iterador se ha creado. Esta matriz nunca cambia durante la vida útil del iterador, por lo que la interferencia es imposible y se garantiza que el iterador no arrojará ConcurrentModificationException.

Además de los altos costos de las actualizaciones de esta aplicación tiene algunos inconvenientes adicionales:

El iterador no reflejará adiciones, eliminaciones o cambios en la lista desde que se creó el iterador. Las operaciones de cambio de elemento en los propios iteradores (remove, set y add) no son compatibles. Estos métodos arrojan UnsupportedOperationException.

Tenga en cuenta que esas colecciones son no pretende ser de utilidad para permitir el bucle y de eliminación de "fácil", pero son especializados colecciones para su uso en situaciones de alta concurrencia, donde muchos hilos necesitan acceso simultáneo a los datos eso aún puede cambiar (pero generalmente cambia raramente). No simplemente reemplace cada ArrayList con un CopyOnWriteArrayList.

+1

Algunas colecciones de java.concurrent. * También. – kan

+0

¿Estás diciendo que _nadie_ de las colecciones 'vanilla' respaldan esto? –

+0

CopyOnWriteArrayList iterator ** does not support support – bestsss

0

Como regla general: cualquier cosa con concurrencia o bloqueo en su nombre, también conocido como. ConcurrentLinkedList, ConcurrentSkipListSet, LinkedBlockingDeque, LinkedBlockingQueue, etc. keySet(), values ​​() de ConcurrentHashMap y ConcurrentSkipListMap y más. La mayoría de java.util.concurrent es ConcurrentModificationException y eso es bueno.

COWArrayList suele ser útil para colecciones de menor tamaño o raramente modificadas ... y debe evitar el método explícito set.

Una nota importante: el uso de Iterator.remove deben ser siempre favorecieron a Collection.remove [cuando AVAILBLE, iterador COWArrayList no soporta eliminar] (excepto CHM.entrySet() que es impl de manera buggy.). Todas las estructuras de acceso no aleatorio se beneficiarán al no tener que buscar el elemento que puede ser O (n).

En general, ConcurrentModificationException fue una idea a medias y es impl. implica algunos efectos secundarios, incl. evitando que funcione la memoria de transacciones de hardware. Impone costos de rendimiento adicionales que rara vez se necesitan. HashMap tiene una impl terrible. con un modCount volátil (que está escrito en la modificación y se lee en cada iteración, sin embargo, read are sorta free en x86).

-1

Probablemente una respuesta poco tarde, pero Java 8 hace que sea mucho más fácil para eliminar los elementos de la colección, mientras que la iteración:

removeIf(Predicate<? super E> filter) 

elimina todos los elementos de esta colección que satisface el predicado dado.

Cuestiones relacionadas