Comment trier une HashMap par valeurs

Comme on a vu dans l'article Comment trier un ArrayList<T>. Dans ce tutoriel on va apprendre à trier une HashMap en java dans l'ordre croissant et décroissant. C'est presque la même chose que dans un ArrayList. Nous allons créer une classe nommé "Comparateur" qui implémente l'interface Comparator pour faire la comparaison dans les deux exemples de ce tutoriel.

1) Trier avec Comparator et mettre le résultat dans TreeMap

Pourquoi faire passer l'instance de la classe Comparateur comme paramètre dans le constructeur de TreeMap? Tout simplement parce que TreeMap<K, V> implémente comme HashMap l'interface Map et a un constructeur TreeMap(Comparator comp). La seule différence est que TreeMap est triée par clés.

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class Tri {

public static void main(String[] args) {

HashMap map = new HashMap();
Comparateur comp = new Comparateur(map);
TreeMap map_apres = new TreeMap(comp);

map.put("A",49);
map.put("B",18);
map.put("C",92);
map.put("D",37);
map.put("E",62);

System.out.println("Avant le tri: "+map);
map_apres.putAll(map);
System.out.println("Après le tri: "+map_apres);
}
}

class Comparateur implements Comparator {

Map tuple;
public Comparateur(HashMap map) {
this.tuple = map;
}

//ce comparateur ordonne les éléments dans l'ordre décroissant
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
if ((int) tuple.get(o1) >= (int) tuple.get(o2)) {
return -1;
} else {
return 1;
}
}
}

2) Trier HashMap avec Collections.sort

Dans cet exemple, on va trier des éléments de type Double. Les éléments sont copiés dans une LinkedList qui implémente l'interface List, puis ils sont triés avec la méthode Collections.sort que nous avons utilisé dans les articles précédents pour trier d'autres collections d'objets. Après le tri, on recopie les élément triés de LinkedList vers une nouvelle table de hachage qui va être retournée en sortie.

public static void main(String[] args) {

HashMap map = new HashMap();

map.put("A",18.5);
map.put("E",76.8);
map.put("C",24.1);
map.put("F",86.2);
map.put("D",5.7);
map.put("B",84.6);

System.out.println("Avant le tri: "+map);
System.out.println("Après le tri: "+triAvecValeur(map));
}

public static HashMap<String, Double> triAvecValeur( HashMap<String, Double> map ){
List<Map.Entry<String, Double>> list =
new LinkedList<Map.Entry<String, Double>>( map.entrySet() );
Collections.sort( list, new Comparator<Map.Entry<String, Double>>(){
public int compare( Map.Entry<String, Double> o1, Map.Entry<String, Double> o2 ){
return (o1.getValue()).compareTo( o2.getValue());
}
});

HashMap<String, Double> map_apres = new LinkedHashMap<String, Double>();
for(Map.Entry<String, Double> entry : list)
map_apres.put( entry.getKey(), entry.getValue() );
return map_apres;
}
Exécution:

Avant le tri: {D=5.7, E=76.8, F=86.2, A=18.5, B=84.6, C=24.1}
Après le tri: {D=5.7, A=18.5, C=24.1, E=76.8, B=84.6, F=86.2}
Pour faire le tri dans le sens décroissant, il suffit de modifier l'ordre de la comparaison dans la fonction compare:

return (o2.getValue()).compareTo( o1.getValue());
Références:
Documentation Oracle - HashMap
TutorialsPoint - The HashMap class
Documentation Comparator
Documentation LinkedHashMap