Ordenar un HashMap en Java

1. Introducción

En este tutorial rápido, aprenderemos cómo ordenar un HashMap en Java .

Más específicamente, veremos cómo ordenar las entradas de HashMap por su clave o valor usando:

  • TreeMap
  • ArrayList y Collections.sort ()
  • TreeSet
  • Usando la API Stream , y finalmente,
  • Usando la biblioteca de Guava

2. Usando un TreeMap

Como sabemos, las claves en TreeMap se ordenan usando su orden natural . Esta es una buena solución cuando queremos ordenar los pares clave-valor por su clave. Entonces, la idea es enviar todos los datos de nuestro HashMap al TreeMap .

Para empezar, definamos un HashMap e inicialicémoslo con algunos datos:

Map map = new HashMap(); Employee employee1 = new Employee(1L, "Mher"); map.put(employee1.getName(), employee1); Employee employee2 = new Employee(22L, "Annie"); map.put(employee2.getName(), employee2); Employee employee3 = new Employee(8L, "John"); map.put(employee3.getName(), employee3); Employee employee4 = new Employee(2L, "George"); map.put(employee4.getName(), employee4);

Para la clase Empleado , tenga en cuenta que hemos implementado Comparable :

public class Employee implements Comparable { private Long id; private String name; // constructor, getters, setters // override equals and hashCode @Override public int compareTo(Employee employee) { return (int)(this.id - employee.getId()); } }

A continuación, almacenamos las entradas en TreeMap utilizando su constructor:

TreeMap sorted = new TreeMap(map);

O el método putAll para copiar los datos:

TreeMap sorted = new TreeMap(); sorted.putAll(map);

¡Y eso es! Para asegurarnos de que las entradas de nuestro mapa estén ordenadas por clave, imprimámoslas:

Annie=Employee{id=22, name="Annie"} George=Employee{id=2, name="George"} John=Employee{id=8, name="John"} Mher=Employee{id=1, name="Mher"}

Como vemos, las claves están ordenadas en orden natural.

3. Usando ArrayList

Por supuesto, podemos ordenar las entradas del mapa con la ayuda de ArrayList . La diferencia clave con el método anterior es que aquí no mantenemos la interfaz del mapa .

3.1. Ordenar por clave

Carguemos el conjunto de claves en una ArrayList :

List employeeByKey = new ArrayList(map.keySet()); Collections.sort(employeeByKey);

Y la salida es:

[Annie, George, John, Mher]

3.2. Ordenar por valor

Ahora, ¿qué pasa si queremos ordenar los valores de nuestro mapa por el campo id del objeto Employee ? También podemos usar una ArrayList para eso.

Primero, copiemos los valores en la lista:

List employeeById = new ArrayList(map.values());

Y después de eso, lo ordenamos:

Collections.sort(employeeById);

Recuerde que esto funciona porque Empleado implementa la interfaz Comparable . De lo contrario, necesitaríamos definir un comparador manual para nuestra llamada a Collections.sort .

Para comprobar los resultados, imprimimos el employeeById :

[Employee{id=1, name="Mher"}, Employee{id=2, name="George"}, Employee{id=8, name="John"}, Employee{id=22, name="Annie"}]

Como vemos, los objetos están ordenados por su campo de identificación .

4. Usando un TreeSet

En caso de que no queramos aceptar valores duplicados en nuestra colección ordenada, existe una buena solución con TreeSet.

Primero, agreguemos algunas entradas duplicadas a nuestro mapa inicial:

Employee employee5 = new Employee(1L, "Mher"); map.put(employee5.getName(), employee5); Employee employee6 = new Employee(22L, "Annie"); map.put(employee6.getName(), employee6);

4.1. Ordenar por clave

Para ordenar el mapa por sus entradas clave:

SortedSet keySet = new TreeSet(map.keySet());

Imprimamos el keySet y veamos el resultado:

[Annie, George, John, Mher]

Ahora tenemos las claves del mapa ordenadas sin los duplicados.

4.2. Ordenar por valor

Asimismo, para los valores del mapa, el código de conversión se ve así:

SortedSet values = new TreeSet(map.values());

Y los resultados son:

[Employee{id=1, name="Mher"}, Employee{id=2, name="George"}, Employee{id=8, name="John"}, Employee{id=22, name="Annie"}]

Como podemos ver, no hay duplicados en la salida. Esto funciona con objetos personalizados cuando anulamos equals y hashCode.

5. Uso de Lambdas y Streams

Desde Java 8, podemos usar la API Stream y expresiones lambda para ordenar el mapa . Todo lo que necesitamos es llamar al método ordenado a través de la tubería de flujo del mapa .

5.1. Ordenar por clave

Para ordenar por clave, usamos el comparador comparingByKey :

map.entrySet() .stream() .sorted(Map.Entry.comparingByKey()) .forEach(System.out::println);

La etapa final de cada etapa imprime los resultados:

Annie=Employee{id=22, name="Annie"} George=Employee{id=2, name="George"} John=Employee{id=8, name="John"} Mher=Employee{id=1, name="Mher"}

De forma predeterminada, el modo de clasificación es ascendente.

5.2. Ordenar por valor

Por supuesto, también podemos ordenar por los objetos de Empleado :

map.entrySet() .stream() .sorted(Map.Entry.comparingByValue()) .forEach(System.out::println);

As we see, the code above prints out a map sorted by the id fields of Employee objects:

Mher=Employee{id=1, name="Mher"} George=Employee{id=2, name="George"} John=Employee{id=8, name="John"} Annie=Employee{id=22, name="Annie"}

Additionally, we can collect the results into a new map:

Map result = map.entrySet() .stream() .sorted(Map.Entry.comparingByValue()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));

Note that we collected our results into a LinkedHashMap. By default, Collectors.toMap returns a new HashMap, but as we know, HashMap doesn't guarantee iterationorder, while LinkedHashMap does.

6. Using Guava

Lastly, a library that allows us to sort the HashMap is Guava. Before we start, it'll be useful to check our write-up about maps in Guava.

Primero, declaremos un Pedido ya que queremos ordenar nuestro mapa por el campo Id. Del empleado :

Ordering naturalOrdering = Ordering.natural() .onResultOf(Functions.forMap(map, null));

Ahora, todo lo que necesitamos es usar ImmutableSortedMap para ilustrar los resultados:

ImmutableSortedMap.copyOf(map, naturalOrdering);

Y una vez más, la salida es un mapa ordenado por el campo id :

Mher=Employee{id=1, name="Mher"} George=Employee{id=2, name="George"} John=Employee{id=8, name="John"} Annie=Employee{id=22, name="Annie"}

7. Resumen

En este artículo, revisamos varias formas de ordenar un HashMap por clave o por valor.

Y analizamos de cerca cómo podemos hacer esto cuando el atributo es una clase personalizada implementando Comparable .

Finalmente, como siempre, el código utilizado durante la discusión se puede encontrar en GitHub.