Trier un HashMap en Java

Trier un HashMap en Java

1. introduction

Dans ce rapide didacticiel, nous allons apprendre à utilisersort a HashMap in Java.

Plus précisément, nous examinerons le tri des entrées deHashMap par leur clé ou leur valeur en utilisant:

  • TreeMap

  • ArrayList etCollections.sort()

  • TreeSet

  • Utilisation de l'APIStream, et enfin,

  • Utilisation de la bibliothèqueGuava 

2. Utilisation d'unTreeMap

Comme nous le savons,keys in TreeMap are sorted using their natural order. 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 nosHashMap dans lesTreeMap.

Pour commencer, définissons unHashMap 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 classeEmployee,note that we’ve implemented 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 leTreeMap by en utilisant son constructeur:

TreeMap sorted = new TreeMap<>(map);

Ou, la méthodeputAll 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 on le voit, les clés sont triées dans l’ordre naturel.

3. Utilisation deArrayList

Bien sûr, nous pouvons trier les entrées de la carte à l'aide deArrayList. La principale différence par rapport à la méthode précédente est quewe don’t maintain the Map interface here.

3.1. Trier par clé

Chargez l'ensemble de clés dans unArrayList:

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 nos valeurs de carte par le champid de l'objetEmployee? Nous pouvons également utiliser unArrayList pour cela.

Commençons par copier 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 parce queEmployee implements the Comparable interface. Sinon, nous devrons définir un comparateur manuel pour notre appel àCollections.sort.

Pour vérifier les résultats, nous imprimons lesemployeeById:

[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 champid.

4. Utilisation d'unTreeSet 

Dans le cas où nousdon’t want to accept duplicate values in our sorted collection, there is a nice solution with TreeSet.

Tout d'abord, ajoutons des 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 en fonction de ses entrées clés:

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

Imprimons leskeySet et voyons le résultat:

[Annie, George, John, Mher]

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

4.2. Trier par valeur

De même, pour les valeurs de carte, le code de conversion se présente comme suit:

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 constater, il n’ya pas de doublons dans la sortie. This works with custom objects when we override equals and hashCode.

5. Utilisation de Lambdas et de flux

Since the Java 8, we can use the Stream API and lambda expressions to sort the map. Tout ce dont nous avons besoin est d’appeler la méthodesorted sur la spipelinestream de la carte.

5.1. Trier par clé

Pour trier par clé, nous utilisons le scomparatorcomparingByKey :

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

L'étape finaleforEach 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 objetsEmployee:

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

Comme nous le voyons, le code ci-dessus imprime une carte triée par les champsid des objetsEmployee:

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

De plus, nous pouvons rassembler les résultats dans une nouvelle carte:

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. Par défaut,Collectors.toMap renvoie un nouveau HashMap, mais comme nous le savons,HashMap doesn’t guarantee iterationorder, tandis queLinkedHashMap le fait.

6. Utilisation de goyave

Enfin, une bibliothèque qui nous permet de trier lesHashMap est Guava. Avant de commencer, il sera utile de vérifier notre article surmaps in Guava.

Tout d'abord, déclarons unOrdering car nous voulons trier notre carte par le champEmployee’sId:

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

Il ne nous reste plus qu'à utiliserImmutableSortedMap pour illustrer les résultats:

ImmutableSortedMap.copyOf(map, naturalOrdering);

Et encore une fois, la sortie est une carte triée par le champid:

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. Sommaire

Dans cet article, nous avons examiné un certain nombre de façons de trier une clé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émentantComparable.

Enfin, comme toujours, le code utilisé lors de la discussion se trouveover on GitHub.