Pregunta sobre loops, iteration, java, hashmap – Iterar a través de un HashMap [duplicado]

3059

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?

En Java 8 usando Lambda Expression:stackoverflow.com/a/25616206/1503859 Nitin Mahesh
¿Cómo tiene esto una puntuación más alta que la pregunta de la que está duplicado? immibis
Checar respuesta :stackoverflow.com/a/53497541/5756557 anandchaugule
Necesito obtener las claves y los valores y agregarlos a una matriz multidimensional burntsugar
@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í. Dean Wild

Tu respuesta

7   la respuesta
3020

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.

Aterricé aquí accidentalmente, ¿por qué hicimosIterator.remove() ¿aquí? OP acaba de pedir una mejor manera de iterar sobre unaMap Puru--
¿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). Peter Mortensen
Tenga en cuenta que it.remove no funcionará con mapas no modificables, como System.getenv () return String Map. J E Carter II
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. Rishabh Agarwal
43

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.

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. sactiw
787

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.

@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 user961954
@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. ohbrobig
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). P Marecki
85

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();
115
for (Map.Entry<String, String> item : hashMap.entrySet()) {
    String key = item.getKey();
    String value = item.getValue();
}
¿Es param el nombre del HashMap? c-an
@ChanjungKim sí, es el Nombre del HashMap heman123
4383

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).

Dado que el mapa no está bajoIterador ¿Cómo en la primera solución la persona ha usado iterador? Rishabh Agarwal
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. Androidcoder
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. doug65536
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? Marco Sulla
60

Más inteligente

for (String key : hashMap.keySet()) {
    System.out.println("Key: " + key + ", Value: " + map.get(key));
}
map.get (clave) para cada iteración no es más inteligente, es mucho más lento ComputerEngineer88
Esto realmente depende de si necesita o no las claves. si no, es más eficiente usar entrySet () ya que hashCode () no se llama. icfantv
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. ComputerEngineer88
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 jasonleonhard

Preguntas relacionadas