Hoy vamos a ver un poco acerca de los distintos métodos de recorrer mapas en java, esto es válido para toda aquella implementación disponible de Map (HashMap, TreeMap, etc...).
Desde la versión 5 de java en adelante, hay nuevas herramientas para recorrer mapas que pueden acelerar el rendimiento de nuestra aplicación de manera notable, como veremos en la conclusión de este artículo. Vamos a ver varios métodos de recorrer mapas, sus ventajas y sus incovenientes.
Imaginemos que tenemos el siguiente mapa:
Map hm = new HashMap(); for (int i=0; i<100000;i++){ hm.put(i, i); }Ahora, vamos a ver distintos métodos de recorridos sobre mapas:
long ini = System.currentTimeMillis(); // Metodo1 for (Map.Entry entry : hm.entrySet()) { System.out.println("Clave: " + entry.getKey() + ", Valor: " + entry.getValue()); } long fin = System.currentTimeMillis(); long ini2 = System.currentTimeMillis(); //Metodo 2. Iteramos solo sobre claves for (Integer clave : hm.keySet()) { System.out.println("Clave: " + clave); } long fin2 = System.currentTimeMillis(); long ini21 = System.currentTimeMillis(); //Metodo2-1.Iteramos sobre valores for (Integer valor : hm.values()) { System.out.println("Valor: " + valor); } long fin21 = System.currentTimeMillis(); long ini3 = System.currentTimeMillis(); //Metodo 3 Iterator> entries = hm.entrySet().iterator(); while (entries.hasNext()) { Map.Entry entry = entries.next(); System.out.println("Clave: " + entry.getKey() + ", Valor: " + entry.getValue()); } long fin3 = System.currentTimeMillis(); long ini4 = System.currentTimeMillis(); // Metodo 4 for (Integer clave : hm.keySet()) { Integer valor = hm.get(clave); System.out.println("Clave: " + clave + ", Valor: " + valor); } long fin4 = System.currentTimeMillis(); System.out.println("tiempo metodo 1: " + (fin-ini)); System.out.println("tiempo metodo 2: " + (fin2-ini2)); System.out.println("tiempo metodo 21: " + (fin21-ini21)); System.out.println("tiempo metodo 3: " + (fin3-ini3)); System.out.println("tiempo metodo 4: " + (fin4-ini4));
Describimos los métodos que hemos implemetado
- Método 1: Recorremos el mapa usando Map.Entry, el cual está disponible desde Java 1.5. Este objeto nos da acceso tanto a las claves como a los valores, devuelve un Set de Map.Entry el cual recorremos con un for-each al estilo de java 5 y superior.
- Método 2: Recorremos solo los valores ( o las claves) ya que no nos hace falta el resto de la información.
- Método 3: Parece redundante con respecto al método 1, introduce un iterador. En la conclusión veremos las ventajas con respecto al método 1, que las hay.
- Método 4: Recorremos el mapa con un iterador (las claves), y hacemos get para obtener los valores en cada pasada.
Metodo1 | Metodo2 | Metodo21 | Metodo3 | Metodo4 | |
1 | 2291 | 1372 | 1406 | 2686 | 2591 |
2 | 2107 | 1428 | 1495 | 2650 | 2637 |
3 | 2033 | 1488 | 1453 | 2821 | 2709 |
4 | 2096 | 1302 | 1564 | 2745 | 2411 |
5 | 2070 | 1503 | 1391 | 2477 | 2610 |
6 | 2161 | 1417 | 1453 | 2627 | 2584 |
7 | 2405 | 1549 | 1361 | 2726 | 2665 |
8 | 2345 | 1418 | 1403 | 2776 | 2536 |
9 | 2343 | 1357 | 1547 | 2592 | 2675 |
10 | 2197 | 1493 | 1320 | 2791 | 2723 |
Media | 2204,8 | 1432,7 | 1439,3 | 2689,1 | 2614,1 |
% | 100 | 64,98 | 65,28 | 121,97 | 118,56 |
- Si solo nos interesan los valores o las claves del mapa, debemos decantarnos por el método 2, ya que son un 35% mas eficientes que el mejor del resto de métodos.
- Si vamos a recorrer el mapa, debemos usar el método 1, ya que como se ve en los resultados es mas eficiente, un 20%, que el resto de recorridos completos.
- Si necesitamos borrar elementos del mapa, debemos usar el método 3, ya que el uso de Map.Entry no nos asegura el borrado. Aunque el rendimiento apriori es un 22% peor que el método 1, al ir eliminando en cada pasada del bucle elementos del mapa, este rendimiento mejorará y se equiparará al método 1 (aunque depende de nuestra política de borrado).
- Si estamos en un sistema anterior a Java 5, debemos usar el método 4 obligatoriamente. Si usamos herramientas de calidad como FindBugs, detectará este tipo de operaciones como ineficiente, invitándonos a cambiarla. Usamos el método 1 (ojo, como digo solo podemos hacerlo si estamos en 1.5 o superior).