Ordina una HashMap in Java

1. Introduzione

In questo rapido tutorial, impareremo come ordinare una HashMap in Java .

Più specificamente, esamineremo l'ordinamento delle voci HashMap in base alla loro chiave o valore utilizzando:

  • TreeMap
  • ArrayList e Collections.sort ()
  • TreeSet
  • Utilizzando il flusso API , e, infine,
  • Utilizzando la libreria Guava

2. Utilizzo di una TreeMap

Come sappiamo, le chiavi in TreeMap vengono ordinate usando il loro ordine naturale . Questa è una buona soluzione quando vogliamo ordinare le coppie chiave-valore in base alla loro chiave. Quindi l'idea è di spingere tutti i dati dalla nostra HashMap nella TreeMap .

Per i principianti, definiamo una HashMap e inizializziamola con alcuni dati:

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);

Per la classe Employee , nota che abbiamo implementato 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()); } }

Successivamente, memorizziamo le voci nella TreeMap utilizzando il suo costruttore:

TreeMap sorted = new TreeMap(map);

Oppure, il metodo putAll per copiare i dati:

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

E questo è tutto! Per assicurarci che le voci della nostra mappa siano ordinate per chiave, stampiamole:

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

Come si vede, le chiavi sono ordinate in ordine naturale.

3. Utilizzo di ArrayList

Naturalmente, possiamo ordinare le voci della mappa con l'aiuto di ArrayList . La differenza fondamentale rispetto al metodo precedente è che qui non manteniamo l' interfaccia Map .

3.1. Ordina per chiave

Carichiamo il set di chiavi in ​​un ArrayList :

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

E l'output è:

[Annie, George, John, Mher]

3.2. Ordina per valore

Ora, cosa succede se vogliamo ordinare i valori della nostra mappa in base al campo id dell'oggetto Employee ? Possiamo usare un ArrayList anche per questo.

Innanzitutto, copiamo i valori nell'elenco:

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

E dopo, lo ordiniamo:

Collections.sort(employeeById);

Ricorda che funziona perché Employee implementa l' interfaccia Comparable . Altrimenti, avremmo bisogno di definire un comparatore manuale per la nostra chiamata a Collections.sort .

Per controllare i risultati, stampiamo il EmployeeById :

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

Come si vede, gli oggetti vengono ordinati in base al loro campo id .

4. Utilizzo di un TreeSet

Nel caso in cui non vogliamo accettare valori duplicati nella nostra raccolta ordinata, c'è una bella soluzione con TreeSet.

Per prima cosa, aggiungiamo alcune voci duplicate alla nostra mappa iniziale:

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

4.1. Ordina per chiave

Per ordinare la mappa in base alle voci chiave:

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

Stampiamo il keySet e vediamo l'output:

[Annie, George, John, Mher]

Ora abbiamo le chiavi della mappa ordinate senza i duplicati.

4.2. Ordina per valore

Allo stesso modo, per i valori della mappa, il codice di conversione ha il seguente aspetto:

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

E i risultati sono:

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

Come possiamo vedere, non ci sono duplicati nell'output. Funziona con oggetti personalizzati quando sovrascriviamo uguale e hashCode.

5. Utilizzo di Lambda e flussi

A partire da Java 8, possiamo utilizzare l'API Stream e le espressioni lambda per ordinare la mappa . Tutto ciò di cui abbiamo bisogno è chiamare il metodo ordinato sulla pipeline di flusso della mappa .

5.1. Ordina per chiave

Per ordinare per chiave, utilizziamo il comparatore comparingByKey:

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

La fase finale di forEach stampa i risultati:

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

Per impostazione predefinita, la modalità di ordinamento è crescente.

5.2. Ordina per valore

Naturalmente, possiamo anche ordinare in base agli oggetti Employee :

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.

Innanzitutto, dichiariamo un ordine in quanto vogliamo ordinare la nostra mappa in base al campo ID dipendente :

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

Ora, tutto ciò di cui abbiamo bisogno è usare ImmutableSortedMap per illustrare i risultati:

ImmutableSortedMap.copyOf(map, naturalOrdering);

E ancora una volta, l'output è una mappa ordinata dal 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. Riepilogo

In questo articolo, abbiamo esaminato una serie di modi per ordinare una HashMap per chiave o per valore.

E abbiamo esaminato da vicino come possiamo farlo quando l'attributo è una classe personalizzata implementando Comparable .

Infine, come sempre, il codice utilizzato durante la discussione può essere trovato su GitHub.