¿Cómo puedo iterar de manera eficiente sobre cada entrada en un mapa de Java?
Frecuentes
Visto 2,643 equipos
3497
Si tengo un objeto que implementa el Map
interfaz en Java y deseo iterar sobre cada par que contiene, ¿cuál es la forma más eficiente de recorrer el mapa?
¿El orden de los elementos dependerá de la implementación del mapa específico que tenga para la interfaz?
30 Respuestas
5292
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
respondido 14 mar '19, 22:03
Si lo hace, no funcionará ya que Entry es una clase anidada en Map. java.sun.com/javase/6/docs/api/java/util/Map.html - ScArcher2
puede escribir la importación como "import java.util.Map.Entry;" y funcionará. - jjujuma
@Pureferret La única razón por la que podría querer usar un iterador es si necesita llamar a su remove
método. Si ese es el caso, esta otra respuesta le muestra cómo hacerlo. De lo contrario, el bucle mejorado como se muestra en la respuesta anterior es el camino a seguir. - Assylias
Creo que el formulario Map.Entry es más claro que importar la clase interna en el espacio de nombres actual. - Josías Yoder
Tenga en cuenta que puede usar map.values()
or map.keySet()
si solo desea recorrer valores o claves. - Paraguay
1327
Para resumir las otras respuestas y combinarlas con lo que sé, encontré 10 formas principales de hacer esto (ver más abajo). Además, escribí algunas pruebas de rendimiento (vea los resultados a continuación). Por ejemplo, si queremos encontrar la suma de todas las claves y valores de un mapa, podemos escribir:
Usar iterador y Entrada del mapa
long i = 0; Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry<Integer, Integer> pair = it.next(); i += pair.getKey() + pair.getValue(); }
Usar foreach y Entrada del mapa
long i = 0; for (Map.Entry<Integer, Integer> pair : map.entrySet()) { i += pair.getKey() + pair.getValue(); }
Usar para cada desde Java 8
final long[] i = {0}; map.forEach((k, v) -> i[0] += k + v);
Usar juego de llaves y foreach
long i = 0; for (Integer key : map.keySet()) { i += key + map.get(key); }
Usar juego de llaves y iterador
long i = 0; Iterator<Integer> itr2 = map.keySet().iterator(); while (itr2.hasNext()) { Integer key = itr2.next(); i += key + map.get(key); }
Usar en y Entrada del mapa
long i = 0; for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) { Map.Entry<Integer, Integer> entry = entries.next(); i += entry.getKey() + entry.getValue(); }
Usando Java 8 API de transmisión
final long[] i = {0}; map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
Usando Java 8 Stream API en paralelo
final long[] i = {0}; map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
Usar IterableMap of
Apache Collections
long i = 0; MapIterator<Integer, Integer> it = iterableMap.mapIterator(); while (it.hasNext()) { i += it.next() + it.getValue(); }
Usar MutableMap de las colecciones de Eclipse (CS)
final long[] i = {0}; mutableMap.forEachKeyValue((key, value) -> { i[0] += key + value; });
Pruebas de rendimiento (modo = tiempo medio, sistema = Windows 8.1 de 64 bits, Intel i7-4790 de 3.60 GHz, 16 GB)
Para un mapa pequeño (100 elementos), la puntuación 0.308 es la mejor
Benchmark Mode Cnt Score Error Units test3_UsingForEachAndJava8 avgt 10 0.308 ± 0.021 µs/op test10_UsingEclipseMap avgt 10 0.309 ± 0.009 µs/op test1_UsingWhileAndMapEntry avgt 10 0.380 ± 0.014 µs/op test6_UsingForAndIterator avgt 10 0.387 ± 0.016 µs/op test2_UsingForEachAndMapEntry avgt 10 0.391 ± 0.023 µs/op test7_UsingJava8StreamApi avgt 10 0.510 ± 0.014 µs/op test9_UsingApacheIterableMap avgt 10 0.524 ± 0.008 µs/op test4_UsingKeySetAndForEach avgt 10 0.816 ± 0.026 µs/op test5_UsingKeySetAndIterator avgt 10 0.863 ± 0.025 µs/op test8_UsingJava8StreamApiParallel avgt 10 5.552 ± 0.185 µs/op
Para un mapa con 10000 elementos, la puntuación 37.606 es la mejor
Benchmark Mode Cnt Score Error Units test10_UsingEclipseMap avgt 10 37.606 ± 0.790 µs/op test3_UsingForEachAndJava8 avgt 10 50.368 ± 0.887 µs/op test6_UsingForAndIterator avgt 10 50.332 ± 0.507 µs/op test2_UsingForEachAndMapEntry avgt 10 51.406 ± 1.032 µs/op test1_UsingWhileAndMapEntry avgt 10 52.538 ± 2.431 µs/op test7_UsingJava8StreamApi avgt 10 54.464 ± 0.712 µs/op test4_UsingKeySetAndForEach avgt 10 79.016 ± 25.345 µs/op test5_UsingKeySetAndIterator avgt 10 91.105 ± 10.220 µs/op test8_UsingJava8StreamApiParallel avgt 10 112.511 ± 0.365 µs/op test9_UsingApacheIterableMap avgt 10 125.714 ± 1.935 µs/op
Para un mapa con 100000 elementos, la puntuación 1184.767 es la mejor
Benchmark Mode Cnt Score Error Units test1_UsingWhileAndMapEntry avgt 10 1184.767 ± 332.968 µs/op test10_UsingEclipseMap avgt 10 1191.735 ± 304.273 µs/op test2_UsingForEachAndMapEntry avgt 10 1205.815 ± 366.043 µs/op test6_UsingForAndIterator avgt 10 1206.873 ± 367.272 µs/op test8_UsingJava8StreamApiParallel avgt 10 1485.895 ± 233.143 µs/op test5_UsingKeySetAndIterator avgt 10 1540.281 ± 357.497 µs/op test4_UsingKeySetAndForEach avgt 10 1593.342 ± 294.417 µs/op test3_UsingForEachAndJava8 avgt 10 1666.296 ± 126.443 µs/op test7_UsingJava8StreamApi avgt 10 1706.676 ± 436.867 µs/op test9_UsingApacheIterableMap avgt 10 3289.866 ± 1445.564 µs/op
Gráficos (pruebas de rendimiento según el tamaño del mapa)
Tabla (pruebas de rendimiento según el tamaño del mapa)
100 600 1100 1600 2100
test10 0.333 1.631 2.752 5.937 8.024
test3 0.309 1.971 4.147 8.147 10.473
test6 0.372 2.190 4.470 8.322 10.531
test1 0.405 2.237 4.616 8.645 10.707
test2 0.376 2.267 4.809 8.403 10.910
test7 0.473 2.448 5.668 9.790 12.125
test9 0.565 2.830 5.952 13.220 16.965
test4 0.808 5.012 8.813 13.939 17.407
test5 0.810 5.104 8.533 14.064 17.422
test8 5.173 12.499 17.351 24.671 30.403
Todas las pruebas están en GitHub.
Respondido 05 ago 19, 21:08
@Viacheslav: muy buena respuesta. Solo me pregunto cómo se obstaculizan las apis de Java8, en su punto de referencia, al capturar lambdas ... (por ejemplo, long sum = 0; map.forEach( /* accumulate in variable sum*/);
captura el sum
de largo, que puede ser más lento que decir stream.mapToInt(/*whatever*/).sum
por ejemplo. Por supuesto, no siempre se puede evitar capturar el estado, pero eso puede ser una adición razonable al banco. - GPI
Tu 8 prueba es incorrecta. accede a la misma variable desde diferentes subprocesos sin sincronización. Cambiar a AtomicInteger
para resolver el problema. - talex
@ZhekaKozlov: mira los valores de error increíblemente grandes. Considere que un resultado de prueba de x±e
implica que hubo resultado dentro del intervalo de x-e
a x+e
, por lo que el resultado más rápido (1184.767±332.968
) rangos desde 852
a 1518
, mientras que el segundo más lento (1706.676±436.867
) corre entre 1270
y 2144
, por lo que los resultados aún se superponen significativamente. Ahora mira el resultado más lento, 3289.866±1445.564
, lo que implica divergir entre 1844
y 4735
y sabes qué que los resultados de estas pruebas no tienen sentido. - Holger
¿Qué hay de comparar las 3 implementaciones principales: HashMap, LinkedHashMap y TreeMap? - Thierry
# 1 y # 6 son exactamente iguales. Utilizando while
contra un for
loop no es una técnica diferente para iterar. Y me sorprende que tengan tanta variación entre ellos en sus pruebas, lo que sugiere que las pruebas no están adecuadamente aisladas de factores externos no relacionados con las cosas que pretende probar. - ErikE
310
En Java 8 puede hacerlo de forma limpia y rápida utilizando las nuevas características de lambdas:
Map<String,String> map = new HashMap<>();
map.put("SomeKey", "SomeValue");
map.forEach( (k,v) -> [do something with key and value] );
// such as
map.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));
El tipo de k
y v
será inferido por el compilador y no es necesario utilizar Map.Entry
más.
¡Pan comido!
Respondido el 07 de Septiembre de 16 a las 09:09
Dependiendo de lo que desee hacer con un mapa, también puede usar la API de transmisión en las entradas devueltas por map.entrySet().stream()
docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html - Vitali Fedorenko
Esto no funcionará si desea hacer referencia a variables no finales declaradas fuera de su expresión lambda desde dentro de forEach () ... - Chris
@Chris Correcto. No funcionará si intentas usar efectivamente no final variables de fuera de la lambda. - El coordinador
251
Sí, el orden depende de la implementación específica del mapa.
@ ScArcher2 tiene la sintaxis Java 1.5 más elegante. En 1.4, haría algo como esto:
Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
Entry thisEntry = (Entry) entries.next();
Object key = thisEntry.getKey();
Object value = thisEntry.getValue();
// ...
}
Respondido 06 Feb 18, 22:02
Prefiero el bucle for que while .. for (Iterator entries = myMap.entrySet (). Iterator (); entries.hasNext ();) {...} Con esta sintaxis, el alcance de las 'entradas' se reduce al bucle for solamente . - Jai
@jpredham Tienes razón en que usar el for
construir como for (Entry e : myMap.entrySet)
no le permitirá modificar la colección, pero el ejemplo como @HanuAthena mencionó que debería funcionar, ya que le da la Iterator
en alcance. (A menos que me falte algo ...) - comprando
IntelliJ me está dando errores en Entry thisEntry = (Entry) entries.next();
: no reconoce Entry
. ¿Es ese pseudocódigo para otra cosa? - JuanK
@JohnK intenta importar java.util.Map.Entry
. - comprando
Esta solución no funcionará si tiene una clave de número entero y una clave de cadena. - usuario5778069
141
El código típico para iterar sobre un mapa es:
Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
String key = entry.getKey();
Thing thing = entry.getValue();
...
}
HashMap
es la implementación del mapa canónico y no ofrece garantías (o aunque no debería cambiar el orden si no se realiza ninguna operación de mutación en él). SortedMap
devolverá entradas basadas en el orden natural de las claves, o un Comparator
, si se proporciona. LinkedHashMap
devolverá entradas en orden de inserción o en orden de acceso dependiendo de cómo se haya construido. EnumMap
devuelve las entradas en el orden natural de las claves.
(Actualización: creo que esto ya no es cierto.) Nota, IdentityHashMap
entrySet
El iterador actualmente tiene una implementación peculiar que devuelve el mismo Map.Entry
instancia para cada elemento en el entrySet
! Sin embargo, cada vez que un nuevo iterador avanza el Map.Entry
Está actualizado.
Respondido 09 Feb 18, 01:02
EnumMap también tiene este comportamiento peculiar junto con IdentityHashMap: Premraj
"LinkedHashMap devolverá entradas en [...] orden de acceso [...]" ... así que accedes a los elementos en el orden en que accedes a ellos? Ya sea tautológico o algo interesante que podría necesitar una digresión. ;-) - jpaugh
@jpaugh Solo accesos directos al LinkedHashMap
contar. Aquellos a través iterator
, spliterator
, entrySet
, etc., no modifique el pedido. - Tom Hawtin - táctica
1. aunque → if? 2. El último párrafo podría beneficiarse de un repaso. - Pedro Mortensen
126
Ejemplo de uso de iterador y genéricos:
Iterator<Map.Entry<String, String>> entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
String key = entry.getKey();
String value = entry.getValue();
// ...
}
Respondido 18 ago 09, 18:08
Deberías poner Iterator
en un bucle for para limitar su alcance. - steve kuo
@SteveKuo ¿Qué quieres decir con "limitar su alcance"? - StudioWorks
@Estudio for (Iterator<Map.Entry<K, V>> entries = myMap.entrySet().iterator(); entries.hasNext(); ) { Map.Entry<K, V> entry = entries.next(); }
. Al usar esa construcción, limitamos el alcance de (visibilidad de la variable) entries
al bucle for. - ComFreek
@ComFreek Oh, ya veo. No sabía que importaba tanto. - StudioWorks
104
Esta es una pregunta de dos partes:
Cómo iterar sobre las entradas de un mapa - @ ScArcher2 tiene contestado eso perfectamente.
¿Cuál es el orden de iteración? - si solo está usando Map
, luego estrictamente hablando, hay sin garantías de pedido. Por lo tanto, no debería confiar en el orden dado por ninguna implementación. sin embargo, el SortedMap
la interfaz se extiende Map
y proporciona exactamente lo que está buscando: las implementaciones siempre proporcionarán un orden de clasificación coherente.
NavigableMap
es otra extensión útil - esto es un SortedMap
con métodos adicionales para buscar entradas por su posición ordenada en el conjunto de claves. Entonces, potencialmente, esto puede eliminar la necesidad de iterar en primer lugar; es posible que pueda encontrar el entry
estás después de usar el higherEntry
, lowerEntry
, ceilingEntry
o floorEntry
métodos. La descendingMap
método incluso te da un método explícito de invertir el orden transversal.
contestado el 23 de mayo de 17 a las 12:05
86
Hay varias formas de iterar sobre el mapa.
A continuación, se muestra una comparación de sus desempeños para un conjunto de datos comunes almacenados en el mapa almacenando un millón de pares de valores clave en el mapa y se iterará sobre el mapa.
1) Utilizando entrySet()
en para cada bucle
for (Map.Entry<String,Integer> entry : testMap.entrySet()) {
entry.getKey();
entry.getValue();
}
Milisegundos 50
2) Utilizando keySet()
en para cada bucle
for (String key : testMap.keySet()) {
testMap.get(key);
}
Milisegundos 76
3) Utilizando entrySet()
e iterador
Iterator<Map.Entry<String,Integer>> itr1 = testMap.entrySet().iterator();
while(itr1.hasNext()) {
Map.Entry<String,Integer> entry = itr1.next();
entry.getKey();
entry.getValue();
}
Milisegundos 50
4) Utilizando keySet()
e iterador
Iterator itr2 = testMap.keySet().iterator();
while(itr2.hasNext()) {
String key = itr2.next();
testMap.get(key);
}
Milisegundos 75
Me he referido this link
.
Respondido 18 Jul 15, 16:07
Los tiempos de ejecución se toman del artículo, que no utiliza Java Microbenchmarking Harness. Por tanto, los tiempos no son fiables, ya que el compilador JIT podría haber optimizado completamente el código, por ejemplo. - AlexB
60
La forma correcta de hacer esto es usar la respuesta aceptada ya que es la más eficiente. Encuentro que el siguiente código parece un poco más limpio.
for (String key: map.keySet()) {
System.out.println(key + "/" + map.get(key));
}
Respondido 17 Oct 11, 01:10
Este no es el mejor enfoque, es mucho más eficiente usar entrySet (). Findbugs marcará este código (ver findbugs.sourceforge.net/…) - jeff olson
@JeffOlson meh, en realidad no. La búsqueda del mapa es O (1), por lo que ambos bucles se comportan de la misma manera. Es cierto que será un poco más lento en un micro benchmark, pero a veces también hago esto porque odio escribir los argumentos de tipo una y otra vez. Además, es muy probable que esto nunca sea su cuello de botella en el rendimiento, así que hágalo si hace que el código sea más legible. - kritzikratzi
más en detalle: O(1) = 2*O(1)
es más o menos la definición de la notación O grande. tienes razón en que funciona un poco más lento, pero en términos de complejidad son iguales. - kritzikratzi
Por colisión o no, quise decir que no importa si tienes algunas colisiones, obviamente es una historia diferente si solo tienes colisiones. así que estás siendo bastante mezquino, pero sí, lo que estás diciendo es verdad. - kritzikratzi
@Jeff Olson: el comentario de que la complejidad del “Big O” no cambia, cuando solo hay un factor constante, es correcto. Aún así, para mí es importante si una operación dura una hora o dos horas. Más importante, debe enfatizarse que el factor es no 2
, como iterando sobre un entrySet()
no soporta una búsqueda en absoluto; es solo un recorrido lineal de todas las entradas. Por el contrario, iterando sobre el keySet()
y realizar una búsqueda por osos clave . búsqueda por clave, por lo que estamos hablando de cero búsquedas vs. n búsquedas aquí, n siendo el tamaño del Map
. Entonces el factor está mucho más allá 2
... - Holger
59
Para su información, también puede usar map.keySet()
y map.values()
si solo está interesado en las claves / valores del mapa y no en el otro.
Respondido el 05 de Septiembre de 08 a las 23:09
50
Con Java 8, puede iterar Map usando forEach y expresión lambda,
map.forEach((k, v) -> System.out.println((k + ":" + v)));
contestado el 15 de mayo de 20 a las 10:05
42
Con Colecciones Eclipse, usarías el forEachKeyValue
método en el MapIterable
interfaz, que es heredada por el MutableMap
y ImmutableMap
interfaces y sus implementaciones.
MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue((key, value) -> result.add(key + value));
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);
Usando una clase interna anónima, puede escribir el código de la siguiente manera:
final MutableBag<String> result = Bags.mutable.empty();
MutableMap<Integer, String> map = Maps.mutable.of(1, "One", 2, "Two", 3, "Three");
map.forEachKeyValue(new Procedure2<Integer, String>()
{
public void value(Integer key, String value)
{
result.add(key + value);
}
});
Assert.assertEquals(Bags.mutable.of("1One", "2Two", "3Three"), result);
Nota: Soy un committer de Eclipse Collections.
Respondido 13 Abr '20, 20:04
37
En teoría, la forma más eficiente dependerá de qué implementación de Map. La forma oficial de hacer esto es llamar map.entrySet()
, que devuelve un conjunto de Map.Entry
, cada uno de los cuales contiene una clave y un valor (entry.getKey()
y entry.getValue()
).
En una implementación idiosincrásica, podría marcar alguna diferencia si usa map.keySet()
, map.entrySet()
o algo mas. Pero no puedo pensar en una razón por la que alguien lo escribiría así. Lo más probable es que lo que hagas no influya en el rendimiento.
Y sí, el orden dependerá de la implementación, así como (posiblemente) del orden de inserción y otros factores difíciles de controlar.
[editar] escribí valueSet()
originalmente pero por supuesto entrySet()
es en realidad la respuesta.
contestado el 04 de mayo de 17 a las 23:05
37
Java 8
Tenemos forEach
método que acepta un expresión lambda. También tenemos stream API. Considere un mapa:
Map<String,String> sample = new HashMap<>();
sample.put("A","Apple");
sample.put("B", "Ball");
Iterar sobre las claves:
sample.keySet().forEach((k) -> System.out.println(k));
Itera sobre valores:
sample.values().forEach((v) -> System.out.println(v));
Iterar las entradas (usando forEach y Streams):
sample.forEach((k,v) -> System.out.println(k + ":" + v));
sample.entrySet().stream().forEach((entry) -> {
Object currentKey = entry.getKey();
Object currentValue = entry.getValue();
System.out.println(currentKey + ":" + currentValue);
});
La ventaja de los flujos es que se pueden paralelizar fácilmente en caso de que lo deseemos. Simplemente necesitamos usar parallelStream()
en lugar de stream()
anterior.
forEachOrdered
vs forEach
con arroyos?
La forEach
no sigue el orden de encuentro (si se define) y es inherentemente no determinista en la naturaleza donde como el forEachOrdered
lo hace. Entonces forEach
no garantiza que se mantendrá el pedido. También revisa este para más.
Respondido 29 Abr '19, 06:04
37
lambda Expresión Java 8
En Java 1.8 (Java 8) esto se ha vuelto mucho más fácil usando para cada método de operaciones agregadas (Operaciones de transmisión) que se parece a los iteradores de Iterable Interfaz.
Simplemente copie y pegue la siguiente declaración en su código y cambie el nombre del mapa hash variable de hm a su variable HashMap para imprimir el par clave-valor.
HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
* Logic to put the Key,Value pair in your HashMap hm
*/
// Print the key value pair in one line.
hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));
// Just copy and paste above line to your code.
A continuación se muestra el código de muestra que intenté usar Expresión Lambda. Esto es tan genial. Deberías intentar.
HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
Random rand = new Random(47);
int i = 0;
while(i < 5) {
i++;
int key = rand.nextInt(20);
int value = rand.nextInt(50);
System.out.println("Inserting key: " + key + " Value: " + value);
Integer imap = hm.put(key, value);
if( imap == null) {
System.out.println("Inserted");
} else {
System.out.println("Replaced with " + imap);
}
}
hm.forEach((k, v) -> System.out.println("key: " + k + " value:" + v));
Output:
Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11
También se puede usar Separador por lo mismo.
Spliterator sit = hm.entrySet().spliterator();
ACTUALIZACIÓN
Incluyendo enlaces de documentación a Oracle Docs. Para más sobre lambda ve a esto aquí y debe leer Operaciones agregadas y para Spliterator ve a esto aquí.
Respondido 30 Abr '19, 14:04
33
Java 8:
Puede usar expresiones lambda:
myMap.entrySet().stream().forEach((entry) -> {
Object currentKey = entry.getKey();
Object currentValue = entry.getValue();
});
Para obtener más información, siga este.
Respondido 06 Feb 18, 03:02
@injecteer: Parece el motivo de las expresiones lambda - humilde novato
No necesita una transmisión si solo desea iterar sobre un mapa. myMap.forEach( (currentKey,currentValue) -> /* action */ );
es mucho más conciso. - Holger
29
Pruebe esto con Java 1.4:
for( Iterator entries = myMap.entrySet().iterator(); entries.hasNext();){
Entry entry = (Entry) entries.next();
System.out.println(entry.getKey() + "/" + entry.getValue());
//...
}
Respondido el 07 de junio de 13 a las 15:06
29
En el mapa se puede iterar sobre keys
y/o values
y/o both (e.g., entrySet)
depende de la persona interesada en_ Me gusta:
Iterato a través del
keys -> keySet()
del mapa:Map<String, Object> map = ...; for (String key : map.keySet()) { //your Business logic... }
Iterato a través del
values -> values()
del mapa:for (Object value : map.values()) { //your Business logic... }
Iterato a través del
both -> entrySet()
del mapa:for (Map.Entry<String, Object> entry : map.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); //your Business logic... }
Además, hay 3 formas diferentes de iterar a través de un HashMap. Son los siguientes:
//1.
for (Map.Entry entry : hm.entrySet()) {
System.out.print("key,val: ");
System.out.println(entry.getKey() + "," + entry.getValue());
}
//2.
Iterator iter = hm.keySet().iterator();
while(iter.hasNext()) {
Integer key = (Integer)iter.next();
String val = (String)hm.get(key);
System.out.println("key,val: " + key + "," + val);
}
//3.
Iterator it = hm.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Integer key = (Integer)entry.getKey();
String val = (String)entry.getValue();
System.out.println("key,val: " + key + "," + val);
}
Respondido el 30 de Septiembre de 20 a las 16:09
24
Más compacto con Java 8:
map.entrySet().forEach(System.out::println);
Respondido 19 Abr '18, 13:04
21
Si tiene un mapa genérico sin tipo, puede usar:
Map map = new HashMap();
for (Map.Entry entry : ((Set<Map.Entry>) map.entrySet())) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
respondido 16 mar '16, 16:03
21
El orden siempre dependerá de la implementación del mapa específico. Con Java 8, puede utilizar cualquiera de estos:
map.forEach((k,v) -> { System.out.println(k + ":" + v); });
o:
map.entrySet().forEach((e) -> {
System.out.println(e.getKey() + " : " + e.getValue());
});
El resultado será el mismo (mismo orden). El entrySet respaldado por el mapa para que obtenga el mismo orden. El segundo es útil ya que le permite usar lambdas, por ejemplo, si solo desea imprimir solo objetos Integer que son mayores de 5:
map.entrySet()
.stream()
.filter(e-> e.getValue() > 5)
.forEach(System.out::println);
El siguiente código muestra la iteración a través de LinkedHashMap y HashMap normal (ejemplo). Verás la diferencia en el orden:
public class HMIteration {
public static void main(String[] args) {
Map<Object, Object> linkedHashMap = new LinkedHashMap<>();
Map<Object, Object> hashMap = new HashMap<>();
for (int i=10; i>=0; i--) {
linkedHashMap.put(i, i);
hashMap.put(i, i);
}
System.out.println("LinkedHashMap (1): ");
linkedHashMap.forEach((k,v) -> { System.out.print(k + " (#="+k.hashCode() + "):" + v + ", "); });
System.out.println("\nLinkedHashMap (2): ");
linkedHashMap.entrySet().forEach((e) -> {
System.out.print(e.getKey() + " : " + e.getValue() + ", ");
});
System.out.println("\n\nHashMap (1): ");
hashMap.forEach((k,v) -> { System.out.print(k + " (#:"+k.hashCode() + "):" + v + ", "); });
System.out.println("\nHashMap (2): ");
hashMap.entrySet().forEach((e) -> {
System.out.print(e.getKey() + " : " + e.getValue() + ", ");
});
}
}
Salida:
LinkedHashMap (1):
10 (#=10):10, 9 (#=9):9, 8 (#=8):8, 7 (#=7):7, 6 (#=6):6, 5 (#=5):5, 4 (#=4):4, 3 (#=3):3, 2 (#=2):2, 1 (#=1):1, 0 (#=0):0,
LinkedHashMap (2):
10 : 10, 9 : 9, 8 : 8, 7 : 7, 6 : 6, 5 : 5, 4 : 4, 3 : 3, 2 : 2, 1 : 1, 0 : 0,
HashMap (1):
0 (#:0):0, 1 (#:1):1, 2 (#:2):2, 3 (#:3):3, 4 (#:4):4, 5 (#:5):5, 6 (#:6):6, 7 (#:7):7, 8 (#:8):8, 9 (#:9):9, 10 (#:10):10,
HashMap (2):
0 : 0, 1 : 1, 2 : 2, 3 : 3, 4 : 4, 5 : 5, 6 : 6, 7 : 7, 8 : 8, 9 : 9, 10 : 10,
Respondido el 30 de Septiembre de 20 a las 18:09
20
public class abcd{
public static void main(String[] args)
{
Map<Integer, String> testMap = new HashMap<Integer, String>();
testMap.put(10, "a");
testMap.put(20, "b");
testMap.put(30, "c");
testMap.put(40, "d");
for (Integer key:testMap.keySet()) {
String value=testMap.get(key);
System.out.println(value);
}
}
}
OR
public class abcd {
public static void main(String[] args)
{
Map<Integer, String> testMap = new HashMap<Integer, String>();
testMap.put(10, "a");
testMap.put(20, "b");
testMap.put(30, "c");
testMap.put(40, "d");
for (Entry<Integer, String> entry : testMap.entrySet()) {
Integer key=entry.getKey();
String value=entry.getValue();
}
}
}
Respondido el 07 de junio de 13 a las 15:06
20
Si tengo un objeto que implementa la interfaz Map en Java y deseo iterar sobre cada par que contiene, ¿cuál es la forma más eficiente de recorrer el mapa?
Si la eficiencia de la reproducción en bucle de las claves es una prioridad para su aplicación, elija una Map
implementación que mantiene las claves en el orden deseado.
¿El orden de los elementos dependerá de la implementación del mapa específico que tenga para la interfaz?
Sí, absolutamente.
- Cosas
Map
las implementaciones prometen un cierto orden de iteración, otras no. - Diferentes implementaciones de
Map
mantener un orden diferente de los pares clave-valor.
Vea esta tabla que creé que resume los diversos Map
implementaciones empaquetadas con Java 11. Específicamente, observe el orden de iteración columna. Haga clic / toque para ampliar.
Puedes ver que hay Digital XNUMXk Map
implementaciones manteniendo un orden:
TreeMap
ConcurrentSkipListMap
LinkedHashMap
EnumMap
NavigableMap
interfaz.
Dos de ellos implementan el NavigableMap
interfaz: TreeMap
& ConcurrentSkipListMap
.
El mas viejo SortedMap
la interfaz es efectivamente suplantada por la nueva NavigableMap
interfaz. Pero puede encontrar implementaciones de terceros que implementen solo la interfaz anterior.
Orden natural
Si quieres una Map
que mantiene sus pares ordenados por el "orden natural" de la clave, utilice TreeMap
or ConcurrentSkipListMap
. El término "orden natural" significa la clase de los implementos de llaves Comparable
. El valor devuelto por el compareTo
El método se utiliza para la comparación en la clasificación.
Orden personalizado
Si desea especificar una rutina de clasificación personalizada para que sus claves se utilicen para mantener un orden ordenado, pase un Comparator
implementación apropiada a la clase de sus claves. Utilizar cualquiera TreeMap
or ConcurrentSkipListMap
, pasando tu Comparator
.
Orden de inserción original
Si desea que los pares de su mapa se mantengan en su orden original en el que los insertó en el mapa, utilice LinkedHashMap
.
Orden de definición de enumeración
Si está utilizando una enumeración como DayOfWeek
or Month
como sus llaves, use el EnumMap
clase. No solo esta clase altamente optimizado para usar muy poca memoria y ejecutarse muy rápido, mantiene sus pares en el orden definido por la enumeración. Para DayOfWeek
, por ejemplo, la clave de DayOfWeek.MONDAY
se encontrará por primera vez cuando se repita, y la clave de DayOfWeek.SUNDAY
será el último.
Otras Consideraciones
Al elegir un Map
implementación, también considere:
- NULL. Algunas implementaciones prohíben / aceptan un NULL como clave y / o valor.
- Simultaneidad. Si está manipulando el mapa a través de subprocesos, debe usar una implementación que admita la simultaneidad. O envuelva el mapa con
Collections::synchronizedMap
(menos preferible).
Ambas consideraciones se tratan en la tabla gráfica anterior.
Respondido 13 Abr '20, 06:04
Comentario tardío sobre una respuesta que también llegó tarde a la fiesta (pero muy informativa). +1 de mí por mencionar EnumMap
, ya que es la primera vez que lo escucho. Probablemente haya muchos casos en los que esto pueda resultar útil. - user991710
15
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry element = (Map.Entry)it.next();
LOGGER.debug("Key: " + element.getKey());
LOGGER.debug("value: " + element.getValue());
}
Respondido el 14 de enero de 16 a las 20:01
14
Puedes hacerlo 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());
}
respondido 16 mar '16, 15:03
14
Utilice Java 8:
map.entrySet().forEach(entry -> System.out.println(entry.getValue()));
Respondido 17 Abr '18, 20:04
12
Una solución iterativa eficaz sobre un mapa es una for
bucle de Java 5 a Java 7. Aquí está:
for (String key : phnMap.keySet()) {
System.out.println("Key: " + key + " Value: " + phnMap.get(key));
}
Desde Java 8 puede usar una expresión lambda para iterar sobre un mapa. Es una mejora forEach
phnMap.forEach((k,v) -> System.out.println("Key: " + k + " Value: " + v));
Si desea escribir un condicional para lambda, puede escribirlo así:
phnMap.forEach((k,v)->{
System.out.println("Key: " + k + " Value: " + v);
if("abc".equals(k)){
System.out.println("Hello abc");
}
});
Respondido el 30 de Septiembre de 20 a las 13:09
11
//Functional Oprations
Map<String, String> mapString = new HashMap<>();
mapString.entrySet().stream().map((entry) -> {
String mapKey = entry.getKey();
return entry;
}).forEach((entry) -> {
String mapValue = entry.getValue();
});
//Intrator
Map<String, String> mapString = new HashMap<>();
for (Iterator<Map.Entry<String, String>> it = mapString.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, String> entry = it.next();
String mapKey = entry.getKey();
String mapValue = entry.getValue();
}
//Simple for loop
Map<String, String> mapString = new HashMap<>();
for (Map.Entry<String, String> entry : mapString.entrySet()) {
String mapKey = entry.getKey();
String mapValue = entry.getValue();
}
Respondido 13 Abr '16, 08:04
10
Sí, como muchas personas estuvieron de acuerdo, esta es la mejor manera de iterar sobre un Map
.
Pero hay posibilidades de tirar nullpointerexception
si el mapa es null
. No te olvides de poner null
.registrarse.
|
|
- - - -
|
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
}
Respondido 06 Feb 18, 22:02
10
Hay muchas formas de hacer esto. A continuación se muestran algunos pasos sencillos:
Suponga que tiene un mapa como:
Map<String, Integer> m = new HashMap<String, Integer>();
Luego, puede hacer algo como lo siguiente para iterar sobre los elementos del mapa.
// ********** Using an iterator ****************
Iterator<Entry<String, Integer>> me = m.entrySet().iterator();
while(me.hasNext()){
Entry<String, Integer> pair = me.next();
System.out.println(pair.getKey() + ":" + pair.getValue());
}
// *********** Using foreach ************************
for(Entry<String, Integer> me : m.entrySet()){
System.out.println(me.getKey() + " : " + me.getValue());
}
// *********** Using keySet *****************************
for(String s : m.keySet()){
System.out.println(s + " : " + m.get(s));
}
// *********** Using keySet and iterator *****************
Iterator<String> me = m.keySet().iterator();
while(me.hasNext()){
String key = me.next();
System.out.println(key + " : " + m.get(key));
}
respondido 22 mar '18, 10:03
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas java dictionary collections iteration or haz tu propia pregunta.
En Java 8 usando Lambda Expression: stackoverflow.com/a/25616206/1503859 - Nitin Mahesh
Java 8: stackoverflow.com/questions/46898/… - akhil_mittal