Trier un HashMap en Java

1. Introduction

Dans ce tutoriel rapide, nous allons apprendre à trier un HashMap en Java .

Plus spécifiquement, nous examinerons le tri des entrées HashMap par leur clé ou valeur en utilisant:

  • TreeMap
  • ArrayList et Collections.sort ()
  • TreeSet
  • Utilisation de l' API Stream , et enfin,
  • Utilisation de la bibliothèque Guava

2. Utilisation d'un TreeMap

Comme nous le savons, les clés de TreeMap sont triées en utilisant leur ordre naturel . C'est une bonne solution lorsque nous voulons trier les paires clé-valeur par leur clé. L'idée est donc de pousser toutes les données de notre HashMap dans le TreeMap .

Pour commencer, définissons un HashMap et initialisons-le avec quelques données:

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

Pour la classe Employee , notez que nous avons implémenté 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()); } }

Ensuite, nous stockons les entrées dans TreeMap en utilisant son constructeur:

TreeMap sorted = new TreeMap(map);

Ou, la méthode putAll pour copier les données:

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

Et c'est tout! Pour vous assurer que nos entrées de carte sont triées par clé, imprimons-les:

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

Comme nous le voyons, les clés sont triées dans un ordre naturel.

3. Utilisation de ArrayList

Bien sûr, nous pouvons trier les entrées de la carte à l'aide de ArrayList . La principale différence par rapport à la méthode précédente est que nous ne maintenons pas l' interface Map ici .

3.1. Trier par clé

Chargeons l'ensemble de clés dans un ArrayList :

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

Et le résultat est:

[Annie, George, John, Mher]

3.2. Trier par valeur

Maintenant, que se passe-t-il si nous voulons trier les valeurs de notre carte par le champ id de l' objet Employee ? Nous pouvons également utiliser une ArrayList pour cela.

Tout d'abord, copions les valeurs dans la liste:

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

Et après cela, nous le trions:

Collections.sort(employeeById);

N'oubliez pas que cela fonctionne car Employee implémente l' interface Comparable . Sinon, nous aurions besoin de définir un comparateur manuel pour notre appel à Collections.sort .

Pour vérifier les résultats, nous imprimons le employeeById :

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

Comme on le voit, les objets sont triés par leur champ id .

4. Utilisation d'un TreeSet

Au cas où nous ne voudrions pas accepter les valeurs en double dans notre collection triée, il existe une solution intéressante avec TreeSet.

Tout d'abord, ajoutons quelques entrées en double à notre carte initiale:

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

4.1. Trier par clé

Pour trier la carte par ses entrées clés:

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

Imprimons le keySet et voyons la sortie:

[Annie, George, John, Mher]

Nous avons maintenant les clés de carte triées sans les doublons.

4.2. Trier par valeur

De même, pour les valeurs de la carte, le code de conversion ressemble à:

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

Et les résultats sont:

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

Comme nous pouvons le voir, il n'y a pas de doublons dans la sortie. Cela fonctionne avec des objets personnalisés lorsque nous remplaçons equals et hashCode.

5. Utilisation de Lambdas et de flux

Depuis Java 8, nous pouvons utiliser l'API Stream et les expressions lambda pour trier la carte . Tout ce dont nous avons besoin est d'appeler la méthode triée sur le pipeline de flux de la carte .

5.1. Trier par clé

Pour trier par clé, nous utilisons le comparateur compareByKey:

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

La dernière étape pour chaque étape imprime les résultats:

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

Par défaut, le mode de tri est croissant.

5.2. Trier par valeur

Bien sûr, nous pouvons également trier par les objets Employé :

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.

Tout d'abord, déclarons une commande car nous voulons trier notre carte par le champ ID de l'employé :

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

Maintenant, tout ce dont nous avons besoin est d'utiliser ImmutableSortedMap pour illustrer les résultats:

ImmutableSortedMap.copyOf(map, naturalOrdering);

Et encore une fois, la sortie est une carte triée par le champ 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. Résumé

Dans cet article, nous avons examiné un certain nombre de façons de trier un HashMap par clé ou par valeur.

Et nous avons examiné de près comment nous pouvons faire cela lorsque l'attribut est une classe personnalisée en implémentant Comparable .

Enfin, comme toujours, le code utilisé lors de la discussion se trouve à l'adresse over sur GitHub.