while remove example collection java iterator

java - remove - ¿Qué operaciones básicas en un Mapa están permitidas mientras se itera sobre él?



java iterator collection example (4)

Digamos que estoy iterando sobre un Mapa en Java ... No tengo claro qué puedo hacer con ese Mapa mientras estoy en proceso de iterar sobre él. Supongo que estoy muy confundido por esta advertencia en el Javadoc para el método de eliminación de la interfaz Iterator:

[...] El comportamiento de un iterador no se especifica si la colección subyacente se modifica mientras la iteración está en progreso de otra manera que llamando a este método.

Sé con certeza que puedo invocar el método de eliminación sin ningún problema. Pero al iterar sobre la colección Map, puedo:

  1. ¿Cambiar el valor asociado con una tecla con el método de colocación de la clase Map (poner con una clave existente)?

  2. Agregue una nueva entrada con el método de poner la clase Map (poner con una nueva clave)?

  3. ¿Eliminar una entrada con el método de eliminación de la clase Map?

Creo que probablemente pueda hacer # 1 de manera segura (ponerlo en una clave existente) pero no hacer # 2 o # 3 de manera segura.

Gracias de antemano por cualquier aclaración sobre esto.


En general, si desea cambiar el Mapa mientras lo itera, debe usar uno de los métodos del iterador. No he probado realmente para ver si el # 1 funcionará, pero los otros definitivamente no lo harán.


No hay una respuesta global. La interfaz del mapa permite la elección de los usuarios. Lamentablemente, creo que todas las implementaciones en el jdk utilizan la implementación de fail-fast (esta es la definición de fail-fast, como se afirma en el HashMap Javadoc ):

Los iteradores devueltos por todos los "métodos de vista de colección" de esta clase son rápidos: si el mapa se modifica estructuralmente en cualquier momento después de que se crea el iterador, de cualquier forma excepto a través del propio método de eliminación del iterador, el iterador arrojará una ConcurrentModificationException . Por lo tanto, frente a la modificación concurrente, el iterador falla rápida y limpiamente, en lugar de arriesgarse a un comportamiento arbitrario y no determinista en un tiempo indeterminado en el futuro.


Si echas un vistazo a la clase HashMap, verás un campo llamado ''modCount''. Así es como el mapa sabe cuándo se ha modificado durante la iteración. Cualquier método que incremente modCount cuando esté iterando hará que arroje una ConcurrentModificationException.

Dicho esto, PUEDE poner un valor en un mapa si la clave ya existe, actualizando efectivamente la entrada con el nuevo valor:

Map<String, Object> test = new HashMap<String, Object>(); test.put("test", 1); for(String key : test.keySet()) { test.put(key, 2); // this works! } System.out.println(test); // will print "test->2"

Cuando se le pregunta si puede realizar estas operaciones ''de forma segura'', no tiene que preocuparse demasiado porque HashMap está diseñado para lanzar esa ConcurrentModificationException tan pronto como se encuentre con un problema como este. Estas operaciones fallarán rápidamente; no dejarán el mapa en mal estado.


Puede usar Iterator.remove() , y si usa un iterador entrySet (de Map.Entry) puede usar Map.Entry.setValue() . Cualquier otra cosa y todas las apuestas están desactivadas; no debe cambiar el mapa directamente, y algunos mapas no permitirán uno o ambos métodos mencionados anteriormente.

Específicamente, su (1), (2) y (3) no están permitidos.

Puede salirse con la suya estableciendo el valor de una clave existente a través del objeto Map , pero la documentación de Set.iterator() excluye específicamente eso y será específico de la implementación:

Si el mapa se modifica mientras una iteración sobre el conjunto está en progreso (excepto a través de la propia operación de eliminación del iterador, o mediante la operación setValue en una entrada de mapa devuelta por el iterador) los resultados de la iteración no están definidos . (énfasis añadido)