2012-01-22 26 views
26

I poner un elementos de la matriz de cadena es un mapa donde los elementos de matriz de cadena es la clave y la frecuencia de palabra es el valor, por ejemplo:colecciones Java - conjunto de claves() vs entrySet() en el mapa

String[] args = {"if","it","is","to","be","it","is","up","me","to","delegate"}; 

entonces el mapa tendrá entradas como [ if:1, it:2 .... ]

Set<String> keys = m.keySet(); 
System.out.println("keyset of the map : "+keys); 

impresiones de todas las teclas: "if","it","is","to","be","it","is","up","me","to","delegate"

Set<Map.Entry<String, Integer>> entrySet = m.entrySet(); 
Iterator<Map.Entry<String, Integer>> i = entrySet.iterator(); 
while(i.hasNext()){ 
    Map.Entry<String, Integer> element = i.next(); 
    System.out.println("Key: "+element.getKey()+" ,value: "+element.getValue()); 
} 

grabados todos los valores de pares de claves:

utilizando el conjunto de impresiones de entrada de todos los valores:

Key: if ,value: 1 
Key: it ,value: 2 
Key: is ,value: 2 
Key: to ,value: 2 
Key: be ,value: 1 
Key: up ,value: 1 
Key: me ,value: 1 
Key: delegate ,value: 1 

pero el bloque de código a continuación deben imprimir exactamente el mismo resultado que el anterior, pero no es así:

Iterator<String> itr2 = keys.iterator(); 
while(itr2.hasNext()){ 
    //System.out.println(itr1.next()+" "); 
    //System.out.println(m.get(itr1.next())+" "); 
    System.out.println("Key: "+itr2.next()+" ,value: "+m.get(itr2.next())); 
} 

imprime:

Key: if ,value: 2 
Key: is ,value: 2 
Key: be ,value: 1 
Key: me ,value: 1 

Pero si la línea uncomment 1 en el bucle mientras es decir

System.out.println(itr1.next()+" "); 

y comentar la línea

System.out.println("Key: "+itr2.next()+" ,value: "+m.get(itr2.next())); 

A continuación, obtener todas las claves: {"if","it","is","to","be","it","is","up","me","to","delegate"};

Si utilizamos m.get() con itr2.next(), entonces el iterador no tiene pocas teclas!

+0

Si está almacenando muchos valores enteros, debe buscar en la biblioteca fastutil en lugar de colecciones j.u. – bmargulies

+0

El conjunto de claves no tendrá repeticiones, supongo que no debería tener la cadena "ello" impresa dos veces. Que está imprimiendo después de esta llamada Establecer keys = m.keySet(); System.out.println ("conjunto de claves del mapa:" + teclas); –

Respuesta

40

Cada llamada al Iterator.next() mueve el iterador al siguiente elemento. Si desea utilizar el elemento actual en más de una declaración o expresión, debe almacenarlo en una variable local. O incluso mejor, ¿por qué no simplemente usas un bucle for-each?

for (String key : map.keySet()) { 
    System.out.println(key + ":" + map.get(key)); 
} 

Además, el bucle sobre el conjunto de entradas es más rápido, porque no consulta el mapa dos veces para cada tecla. También las implementaciones Map.Entry generalmente implementan el método toString(), por lo que no tiene que imprimir el par clave-valor manualmente.

for (Entry<String, Integer> entry : map.entrySet()) { 
    System.out.println(entry); 
} 
+4

Gracias por mencionar este punto tan importante: use el conjunto de entradas para evitar la sobrecarga innecesaria de la llamada a 'get()'. – erickson

+0

"porque no consulta el mapa dos veces para cada clave" ¿por qué dos veces? Pensé que solo consultas una vez cuando haces map.get (clave)? – HenryNguyen

+1

@HenryNguyen Creo que quiso decir que lo está consultando una vez cuando usa el iterador para buscar la clave –

1

Un Iterator avanza solo, si lo leyó una vez, ya está hecho. Su

m.get(itr2.next()); 

es la lectura de la siguiente valor de itr2.next();, es por eso que se echa en falta unos pocos (cada otros en realidad no pocos, teclas).

3

Cada vez que llame a itr2.next() obtendrá un valor distinto. No tiene el mismo valor Solo debe llamar esto una vez en el ciclo.

Iterator<String> itr2 = keys.iterator(); 
    while(itr2.hasNext()){ 
     String v = itr2.next(); 
     System.out.println("Key: "+v+" ,value: "+m.get(v)); 
    } 
+2

En el libro Efectivo de Java se menciona el mismo error y es por eso que usar el bucle Foreach es el preferido. –

+0

Tuviste la suerte de tener incluso un número de entradas en el mapa; de lo contrario, podrías encontrar una excepción RuntimeException –

+0

+1 al comentario de Amir. A menos que necesite eliminar elementos de la colección, el uso del iterador directamente solo introducirá la posibilidad de errores. Debería usar el estilo de bucle foreach para bucles de lectura simples. –

2

de recorrido sobre el mapa grande entrySet() es mucho mejor que el keySet(). Compruebe this tutorial cómo optimizar el recorrido sobre el objeto grande con la ayuda de entrySet() y cómo ayuda a la optimización del rendimiento.

0

Hola @NCOMCOMPOOP para hacer las cosas simples, tenga en cuenta que cada vez que lo hace it2.next() el puntero se mueve al siguiente elemento, es decir, aquí si lo observa cuidadosamente, entonces la salida está perfectamente bien según la lógica has escrito .

Esto le puede ayudar a comprender mejor:

primera iteración del bucle While (puntero se encuentra antes de la primera parte): Clave: si, valor: 2 //{itr2.next()=if; m.get (itr2.next() = it) => 2}

2da iteración del ciclo While (el puntero está antes del tercer elemento): Clave: es, valor: 2 // {itr2.next() = es; m.get (itr2.next() = a) => 2}

tercera iteración del bucle Mientras (puntero es antes de que el elemento de quinta): Clave: ser, valor: 1 // {itr2.next() = "ser"; m.get (itr2.next() = "arriba") => "1"}

4ª iteración del bucle While (el puntero está antes del 7 ° elemento): Clave: yo, valor: 1 // {itr2 .next() = "yo"; m.get (itr2.next() = "delegado") => "1"}

Clave: si, valor: 1 Clave: es, valor: 2 Clave: es, valor: 2 clave: a, valor: 2 clave: ser, valor: 1 clave: hasta, valor: 1 clave: yo, valor: 1 clave: delegado, valor: 1

imprime:

clave: si, valor: 2
Clave: es, valor: 2 Clave: ser, valor: 1 Clave: yo, valor: 1

Cuestiones relacionadas