Iterar a través de un HashMap [duplicado]

Posible duplicado:
¿Cómo iterar eficientemente sobre cada entrada en un 'Mapa'?

¿Cuál es la mejor manera de iterar sobre los elementos en unaHashMap?

 Nitin Mahesh25 jul. 2015 20:33
En Java 8 usando Lambda Expression:stackoverflow.com/a/25616206/1503859
 immibis16 feb. 2015 03:50
¿Cómo tiene esto una puntuación más alta que la pregunta de la que está duplicado?
 anandchaugule13 feb. 2019 14:56
 burntsugar01 jul. 2009 02:05
Necesito obtener las claves y los valores y agregarlos a una matriz multidimensional
 Dean Wild14 mar. 2016 10:14
@immibis probablemente porque muchas personas usan HashMaps de manera instintiva sin considerar otras implementaciones de mapas. Luego, cuando, inevitablemente, se quedan atascados tratando de recorrer su HashMap, introducen "Iterar a través de un HashMap" en Google, guiándolos directamente aquí.

Respuestas a la pregunta(7)

Solución de preguntas

Iterar a través de laentrySet() al igual que:

public static void printMap(Map mp) {
    Iterator it = mp.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pair = (Map.Entry)it.next();
        System.out.println(pair.getKey() + " = " + pair.getValue());
        it.remove(); // avoids a ConcurrentModificationException
    }
}

Leer más sobreMap.

 Rishabh Agarwal06 dic. 2017 07:45
Ya queMapa no está bajoIterador clase,¿Cómo se puede usar iterador con mapa? Sólo la lista, la cola y el conjunto son iterables.
 Puru--13 abr. 2014 20:42
Aterricé aquí accidentalmente, ¿por qué hicimosIterator.remove() ¿aquí? OP acaba de pedir una mejor manera de iterar sobre unaMap
 Peter Mortensen06 feb. 2018 23:57
¿Quizás actualizar esto para Java 8? (Por ejemplo, proporciona dos versiones, una para Java 8 anterior y otra que solo funciona en Java 8).
 J E Carter II14 may. 2014 17:06
Tenga en cuenta que it.remove no funcionará con mapas no modificables, como System.getenv () return String Map.
 Paŭlo Ebermann21 ago. 2017 19:57
@etlds En realidad, Java 1.2 introdujo Iterator, pero no tenía genéricos en ese entonces. Los genéricos solo fueron agregados en 1.5.
 technazi19 abr. 2018 06:06
ConcurrentHashMap es una implementación de la interfaz de ConcurrentMap. La interfaz ConcurrentMap extiende la interfaz del mapa. La confusión se debe a que la pregunta formulada específicamente para HashMap. HashMap es una implementación de la interfaz de Map. Siempre es mejor declarar un Mapa de Hash Concurrente como: Mapa <Cadena, Cadena> myMap = nuevo Mapa de Hash Concurrente <Cadena, Cadena> (); en lugar de: ConcurrentHashMap <String, String> myMap = new ConcurrentHashMap <String, String> (); Esta primera práctica permite la extensibilidad. Esa es la razón por la que esta es una respuesta madura.
 Androidcoder22 oct. 2017 23:56
Obtengo advertencias de asignación sin marcar y sin marcar para '(Map.Entry) it.next ()'. Agregué un cheque a la entrada Mapa, Entrada: 'Map.Entry <Integer, MyObject> entry' para evitar otros problemas.
 Whimusical19 jul. 2012 14:41
¿Hay alguna diferencia en las posibilidades de ConcurrentModificationExceptions entre ambas sintaxis en términos de llamar a remove () o no? Algunas respuestas implican aseveraciones contradictorias (primero contra cuarto comentarios)
 etlds05 mar. 2013 20:37
La interfaz del iterador es genérica desde 1.2. Debe ser iterador <E>
 Danny26 ene. 2012 20:07
@vimukthi, ¿qué quieres decir con una solución para eso? Sólo quite elit.remove(); línea.
 Impulse The Fox18 sept. 2017 09:52
Por favor no uses más Iterator.
 Jwan62207 ene. 2016 17:03
Entonces, los pasos de la imagen general parecen ser 1. convertir a un conjunto utilizando entrySet 2. convertirlo en un iterador y 3. llamar a hasNext y convertir cada siguiente objeto en un objeto Map.Entry?
 Hele15 dic. 2014 06:19
La respuesta de @harto es mejor ya que le dice al lector cómo usar esto en una variedad de casos. El rango de aplicación de su solución es pequeño. Muy pequeño.
 apraetor12 may. 2017 00:00
@ JürgenK. No,it.hasNext() devuelve un valor booleano en función de si el iterador tiene otro elemento más allá del actual pero no avanza el estado del iterador. El iterador no avanza al siguiente elemento hasta queit.next() se llama.
 Mader Levap01 mar. 2019 14:05
Lo considero una mala respuesta. OP pedía solo una iteración sobre el mapa, no cómo modificar el mapa durante la iteración.
 Jürgen K.19 oct. 2015 19:38
¿No salta por encima de la primera entrada usando "linewhile (it.hasNext ())"?
 NimChimpsky31 may. 2017 04:37
@Alex si yo también
 flipperweid06 jul. 2017 15:49
¡Esta API no es intuitiva, por lo que busco esta respuesta en Google repetidamente y fue al menos 20 veces en esta respuesta!
 Chad Okere28 ene. 2012 18:29
El para(Map.Entry<String, Object> cursor : map.entrySet()) {...} la sintaxis es mucho mejor
 Moebius03 sept. 2014 15:13
El tipo completo de iterador es: import java.util.Iterator;
 ashishduh02 dic. 2016 19:22
Todos diciendo esofor (Map.Entry<String, Object> cursor : map.entrySet()) es mejor que esto es ignorar el hecho de que todavía recibirá unaConcurrentModificationException utilizando ese método. La respuesta seleccionada sigue siendo el mejor método para iterar a través de unMap.
 Victor28 feb. 2014 16:46
Considero que la respuesta de arvnid, a pesar de ser solo una copia / pegar o no. (Estoy de acuerdo en que es ético dar los créditos apropiados a quien pertenece)
 nemetroid29 jun. 2017 10:22
@ashishduh La respuesta seleccionada es solo la mejor en elcaso especial donde necesitas modificar el mapa durante la iteración. Para todos los demás usos, es preferible utilizar un bucle for mejorado.
 fresh_dev25 oct. 2011 10:56
@ karim79 ¿qué piensas de la siguiente manera:Map<Integer, Integer> map = new HashMap<Integer, Integer>(); for (Map.Entry<Integer, Integer> entry : map.entrySet()) { System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); }
 Benjamin Wootton16 dic. 2010 10:22
Aunque es antiguo, esto ayudará a evitar ConcurrentModificationExceptions sobre el nuevo estilo foreach en las respuestas a continuación. Puede, por ejemplo, eliminar a través del iterador separado.
 vimukthi10 ene. 2012 10:47
llamando a 'it.remove (); 'está vaciando el mapa, por lo que no es reutilizable si este mapa fuera una variable de clase. ¿Tienes alguna solución para eso?

da entrada, vaya a través deentrySet. Si solo necesitas los valores, entonces hay lavalues() método. Y si solo necesitas las llaves, entonces usakeyset().

Una mala práctica sería iterar a través de todas las claves, y luego dentro del bucle, siempre hagamap.get(key) para obtener el valor. Si estás haciendo eso, entonces la primera opción que escribí es para ti.

 sactiw24 ene. 2014 09:25
Otro punto importante, el Conjunto devuelto por keySet () y la Colección devuelta por los valores () están respaldados por el Mapa original. Es decir, si realiza alguna modificación en ellos, se reflejarán nuevamente en el Mapa, sin embargo, ambos no admiten los métodos add () y addAll (), es decir, no puede agregar una nueva clave al Conjunto o al nuevo valor en la colección.

Cómo iterar sobre un mapa en Java:

Hay varias formas de iterar sobre unMap en java Vamos a repasar los métodos más comunes y revisar sus ventajas y desventajas. Dado que todos los mapas en Java implementan la interfaz de mapas, las siguientes técnicas funcionarán para cualquier implementación de mapas (HashMap, TreeMap, LinkedHashMap, Hashtable, etc.)

Método 1: Iterando sobre entradas usando un bucle For-Each.

Este es el método más común y es preferible en la mayoría de los casos. Se debe utilizar si necesita claves de mapa y valores en el bucle.

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

Tenga en cuenta que el bucle For-Each se introdujo en Java 5, por lo que este método funciona solo en las versiones más nuevas del lenguaje. También se lanzará un bucle For-Each.NullPointerException Si intenta iterar sobre un mapa que es nulo, así que antes de iterar siempre debe verificar las referencias nulas.

Método # 2: Iterando sobre claves o valores utilizando un bucle For-Each.

Si solo necesita claves o valores del mapa, puede iterar sobre keySet o valores en lugar de entrySet.

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

// Iterating over keys only
for (Integer key : map.keySet()) {
    System.out.println("Key = " + key);
}

// Iterating over values only
for (Integer value : map.values()) {
    System.out.println("Value = " + value);
}

Este método da una ligera ventaja de rendimiento sobreentrySet iteración (alrededor del 10% más rápido) y es más limpio.

Método # 3: Iterando usando el iterador.

Usando Genéricos:

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry<Integer, Integer> entry = entries.next();
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

Sin genéricos:

Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry entry = (Map.Entry) entries.next();
    Integer key = (Integer)entry.getKey();
    Integer value = (Integer)entry.getValue();
    System.out.println("Key = " + key + ", Value = " + value);
}

También puedes usar la misma técnica para iterar sobrekeySet o valores.

Este método puede parecer redundante, pero tiene sus propias ventajas. En primer lugar, es la única forma de iterar sobre un mapa en versiones anteriores de Java. La otra característica importante es que es el único método que le permite eliminar entradas del mapa durante la iteración llamandoiterator.remove(). Si intenta hacer esto durante la iteración For-Each, obtendrá "resultados impredecibles" de acuerdo conJavadoc.

Desde el punto de vista del rendimiento, este método es igual a una iteración For-Each.

Método # 4: Iterando sobre las teclas y buscando valores (ineficientes).

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
    Integer value = map.get(key);
    System.out.println("Key = " + key + ", Value = " + value);
}

Esto podría parecer una alternativa más limpia para el método # 1, pero en la práctica es bastante lento e ineficiente, ya que obtener valores con una clave puede llevar mucho tiempo (este método en diferentes implementaciones de mapas es 20% -200% más lento que el método # 1 ). Si tiene instalado FindBugs, detectará esto y le advertirá sobre una iteración ineficiente. Este método debe ser evitado.

Conclusión:

Si solo necesita claves o valores del mapa, use el método # 2. Si está atascado con una versión anterior de Java (menos de 5) o planea eliminar entradas durante la iteración, debe usar el método # 3. De lo contrario, utilice el método # 1.

 user96195413 abr. 2019 10:45
@ohbrobig es O (1), pero ese es el tiempo de ejecución, así es como se escala. No significa que necesariamente obtendrá el valor en el primer ciclo. El Método # 4 definitivamente será más lento que el Método # 1
 ohbrobig03 jun. 2018 15:09
@arvind ¿Cómo podría el método # 4 ser ineficiente alguna vez? Por definición, llamandoget() Siempre es O (1) para un HashMap. Esa es la definición de un HashMap y el usuario solicitó un HashMap. No entiendo por qué esto es tan altamente votado. Si va a hacer referencia al enlace de otra persona, asegúrese de que realmente tenga sentido para la pregunta formulada.
 P Marecki29 feb. 2016 13:34
Vamos a añadir el pequeño caevet, que en caso deConcurrentMaps, iteración enkeySet() se bloqueará en general (no hay garantía de que existan valores para las claves recopiladas anteriormente). Por otro lado, el uso de iteradores o entradas es seguro (siempre se refieren a objetos existentes).

Puedes iterar a través de las entradas en unMap de varias maneras. Obtenga cada clave y valor de esta manera:

Map<?,?> map = new HashMap<Object, Object>();
for(Entry<?, ?> e: map.entrySet()){
    System.out.println("Key " + e.getKey());
    System.out.println("Value " + e.getValue());
}

O puede obtener la lista de claves con

Collection<?> keys = map.keySet();
for(Object key: keys){
    System.out.println("Key " + key);
    System.out.println("Value " + map.get(key));
}

Si solo desea obtener todos los valores y no está preocupado por las claves, puede usar:

Collection<?> values = map.values();
for (Map.Entry<String, String> item : hashMap.entrySet()) {
    String key = item.getKey();
    String value = item.getValue();
}
 c-an27 feb. 2019 01:53
¿Es param el nombre del HashMap?
 heman12327 feb. 2019 23:29
@ChanjungKim sí, es el Nombre del HashMap

Si solo está interesado en las claves, puede iterar a través dekeySet() del mapa:

Map<String, Object> map = ...;

for (String key : map.keySet()) {
    // ...
}

Si solo necesitas los valores, usavalues():

for (Object value : map.values()) {
    // ...
}

Finalmente, si quieres tanto la clave como el valor, usaentrySet():

for (Map.Entry<String, Object> entry : map.entrySet()) {
    String key = entry.getKey();
    Object value = entry.getValue();
    // ...
}

Una advertencia: si desea eliminar elementos a mitad de la iteración, deberá hacerlo a través de un iterador (verla respuesta de karim79). Sin embargo, cambiar los valores de los elementos es correcto (verMap.Entry).

 Rishabh Agarwal06 dic. 2017 07:44
Dado que el mapa no está bajoIterador ¿Cómo en la primera solución la persona ha usado iterador?
 Androidcoder25 jul. 2018 18:24
Recibo un error de tipos incompatibles para 'Map.Entry entry' y 'Map.Entry <Integer, HashMap> entry: "Objeto requerido, entrada encontrada". Estoy mapeando enteros a los hashmaps. Tener que usar el conjunto de claves para el bucle debido a esto y extraer el valor a través de 'value = (HashMap) integertomap.get (clave)', aunque menos eficiente que si pudiera usar entrySet sin iterater según su ejemplo.
 doug6553607 ago. 2017 00:05
Las preguntas de rendimiento de @MarcoSulla así dependen, debe medir y ver en los casos que sean importantes. Es probable que utilizandoentrySet es más rápido porque puede evitar hacer una búsqueda para cada entrada. La implementación de lo particular.Map Determina qué camino es mejor y por cuánto. La presión del GC en ese punto también podría ser un factor.
 DaMainBoss26 jul. 2011 20:18
Entonces, ¿cómo hacer un bucle a través de 2 mapas simultáneamente? ¿Utilizando el método entrySet? Intenté usar && pero no funcionó
 Marco Sulla18 abr. 2017 10:54
Para obtener los valores y las claves, no solo es más sencillo utilizar la primeraforeach Ejemplo y obtener el valor dentro del bucle, convalue = map.get(key)? Es el rendimiento deentrySet ¿más alto?
 rogerdpack06 oct. 2011 01:14
Solo es más eficiente usar entrySet cuando necesita tanto claves como valores. Si solo necesita uno o el otro, simplemente use ese:stackoverflow.com/questions/3870064/…
 harto27 jul. 2011 06:08
Utilice dos iteradores. Vea la respuesta aceptada, por ejemplo, el uso de un iterador.
 sactiw24 ene. 2014 09:27
Otro punto importante, el Conjunto devuelto por keySet () y la Colección devuelta por los valores () están respaldados por el Mapa original. Es decir, si realiza alguna modificación en ellos, se reflejarán nuevamente en el Mapa, sin embargo, ambos no admiten los métodos add () y addAll (), es decir, no puede agregar una nueva clave al Conjunto o al nuevo valor en la colección.

Más inteligente

for (String key : hashMap.keySet()) {
    System.out.println("Key: " + key + ", Value: " + map.get(key));
}
 ComputerEngineer8818 abr. 2013 23:30
map.get (clave) para cada iteración no es más inteligente, es mucho más lento
 icfantv06 oct. 2011 00:33
Esto realmente depende de si necesita o no las claves. si no, es más eficiente usar entrySet () ya que hashCode () no se llama.
 ComputerEngineer8816 abr. 2016 15:11
map.entrySet () que devuelve entradas que ya contienen la clave y el valor. De esta manera, no tiene que llamar a hashCode () y buscar el hash durante la iteración.
 jasonleonhard06 ago. 2017 00:40
Sintaxis de Java 8. Todavía puede no funcionar para el desarrollo de Android. "Android no pretende ser 100% compatible con ninguna versión de Java SE API, ni 6 ni 8 ni ninguna ... El JRE es el Java Runtime Environment, mientras que el JDK es el Java Development Kit. Es el JDK que necesita. para el desarrollo de aplicaciones de Android junto con el Android SDK.Dec 9, 2013 "fuente

Su respuesta a la pregunta