A menudo usamos mapas para almacenar una colección del tipo key-value. Luego, en algún momento, a menudo necesitamos iterar sobre ellos.

En este tutorial, compararemos diferentes métodos de iteración de mapas, destacando cuándo puede ser beneficioso utilizar Map.Entry. Luego, aprenderemos cómo se puede usar Map.Entry para crear una tupla. Finalmente, crearemos una lista ordenada de tuplas.

Optimización de la iteración de un mapa

Supongamos que tenemos un mapa de títulos de libros con el nombre del autor como clave:

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

map.put("Robert C. Martin", "Clean Code");
map.put("Joshua Bloch", "Effective Java");

Comparemos dos métodos para obtener todas las claves y valores de nuestro mapa.

Consideremos lo siguiente:

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

Aquí, el bucle itera sobre keySet. Para cada clave, obtenemos el valor correspondiente usando Map.get. Si bien esta es una forma obvia de usar todas las entradas en el mapa, requiere dos operaciones para cada entrada: una para obtener la siguiente clave y otra para buscar el valor con get.

Si solo necesitamos las claves en un mapa, keySet es una buena opción. Sin embargo, existe una forma más rápida de obtener tanto las claves como los valores.

Reescribamos nuestra iteración para usar entrySet:

for (Map.Entry book: map.entrySet()) {
     System.out.println("key: " + book.getKey() + " value: " + book.getValue());
 }

En este ejemplo, nuestro bucle se encuentra sobre una colección de objetos Map.Entry. Como Map.Entry almacena la clave y el valor juntos en una clase, los obtenemos en una sola operación.

Las mismas reglas se aplican al uso de operaciones sobre streams de Java 8. Transmitir a través del entrySet y trabajar con objetos Entry es más eficiente y puede requerir menos código.

Tuplas

Primero consideremos una clase Libro:

public class Libro {
     private String titulo;
     private String autor;
 public Book(String titulo, String autor) {     this.titulo = titulo;     this.autor = autor; } ...
 }

A continuación, creemos una tupla Map.Entry con el ISBN como clave y el objeto Book como valor:

Map.Entry<String, Libro> tupla; 

Finalmente, creemos una instancia de nuestra tupla con AbstractMap.SimpleEntry:

tupla = new AbstractMap.SimpleEntry<>("9780134685991", new Book("Effective Java 3d Edition", "Joshua Bloch")); 

Crear una lista ordenada de tuplas

Cuando se trabaja con tuplas, a menudo es útil tenerlas como una lista ordenada.

Primero, definiremos nuestra lista de tuplas:

List<Map.Entry<String, Libro>> tuplasOrdenadas = new ArrayList<>(); 

En segundo lugar, agreguemos algunas entradas a nuestra lista:

tuplasOrdenadas.add(new AbstractMap.SimpleEntry<>("9780134685991", new Book("Effective Java 3d Edition", "Joshua Bloch")));

tuplasOrdenadas.add(new AbstractMap.SimpleEntry<>("9780132350884", new Book("Clean Code","Robert C Martin")));

Comparando con Map

Para comparar las diferencias con un mapa, agreguemos una nueva entrada con una clave que ya existe:

tuplasOrdenadas.add(new AbstractMap.SimpleEntry<>("9780132350884",    new Book("Clean Code", "Robert C Martin"))); 

En segundo lugar, iteraremos sobre nuestra lista, mostrando todas las claves y valores:

for (Map.Entry tupla : tuplasOrdenadas) {
     System.out.println("Clave: " + tupla.getKey() + " valor: " + tupla.getValue());
 }

lo cual produce la siguiente salida:

clave: 9780134685991 valor: Libro{titulo='Effective Java 3d Edition', autor='Joshua Bloch'}
 clave: 9780132350884 valor: Libro{titulo='Clean Code', autor='Robert C Martin'}
 clave: 9780132350884 valor: Libro{titulo='Clean Code', autor='Robert C Martin'}

Tenga en cuenta que podemos tener claves duplicadas, a diferencia de un mapa básico, donde cada clave tiene que ser única. Esto se debe a que hemos usado una implementación de List para almacenar nuestros objetos SimpleEntry, lo que significa que todos los objetos son independientes entre sí.

Listas de objetos Entry

Debemos tener en cuenta que el propósito de Entry no es actuar como una tupla genérica. Las clases de la biblioteca a menudo proporcionan una clase de par genérica para este propósito.

Sin embargo, es posible que tengamos que trabajar temporalmente con listas de entradas mientras preparamos datos para un mapa o extrae datos de uno.

Categorized in:

Tagged in: