Comparaison de deux HashMaps en Java

1. Vue d'ensemble

Dans ce didacticiel, nous allons explorer différentes façons de comparer deux HashMaps en Java .

Nous discuterons de plusieurs façons de vérifier si deux HashMaps sont similaires. Nous utiliserons également l'API Java 8 Stream et Guava pour obtenir les différences détaillées entre les différents HashMaps .

2. Utilisation de Map.equals ()

Tout d'abord, nous utiliserons Map.equals () pour vérifier si deux HashMaps ont les mêmes entrées:

@Test public void whenCompareTwoHashMapsUsingEquals_thenSuccess() { Map asiaCapital1 = new HashMap(); asiaCapital1.put("Japan", "Tokyo"); asiaCapital1.put("South Korea", "Seoul"); Map asiaCapital2 = new HashMap(); asiaCapital2.put("South Korea", "Seoul"); asiaCapital2.put("Japan", "Tokyo"); Map asiaCapital3 = new HashMap(); asiaCapital3.put("Japan", "Tokyo"); asiaCapital3.put("China", "Beijing"); assertTrue(asiaCapital1.equals(asiaCapital2)); assertFalse(asiaCapital1.equals(asiaCapital3)); }

Ici, nous créons trois objets HashMap et ajoutons des entrées. Ensuite, nous utilisons Map.equals () pour vérifier si deux HashMaps ont les mêmes entrées.

Le fonctionnement de Map.equals () consiste à comparer les clés et les valeurs à l'aide de la méthode Object.equals () . Cela signifie qu'il ne fonctionne que lorsque les objets clé et valeur implémentent correctement equals () .

Par exemple, Map.equals () ne fonctionne pas lorsque le type de valeur est tableau, car la méthode equals () d' un tableau compare l'identité et non le contenu du tableau:

@Test public void whenCompareTwoHashMapsWithArrayValuesUsingEquals_thenFail() { Map asiaCity1 = new HashMap(); asiaCity1.put("Japan", new String[] { "Tokyo", "Osaka" }); asiaCity1.put("South Korea", new String[] { "Seoul", "Busan" }); Map asiaCity2 = new HashMap(); asiaCity2.put("South Korea", new String[] { "Seoul", "Busan" }); asiaCity2.put("Japan", new String[] { "Tokyo", "Osaka" }); assertFalse(asiaCity1.equals(asiaCity2)); }

3. Utilisation de l' API Java Stream

Nous pouvons également implémenter notre propre méthode pour comparer HashMaps à l'aide de l' API Java 8 Stream :

private boolean areEqual(Map first, Map second) { if (first.size() != second.size()) { return false; } return first.entrySet().stream() .allMatch(e -> e.getValue().equals(second.get(e.getKey()))); }

Pour plus de simplicité, nous avons implémenté la méthode areEqual () que nous pouvons désormais utiliser pour comparer des objets HashMap :

@Test public void whenCompareTwoHashMapsUsingStreamAPI_thenSuccess() { assertTrue(areEqual(asiaCapital1, asiaCapital2)); assertFalse(areEqual(asiaCapital1, asiaCapital3)); }

Mais nous pouvons également personnaliser notre propre méthode areEqualWithArrayValue () pour gérer les valeurs de tableau en utilisant Arrays.equals () pour comparer deux tableaux:

private boolean areEqualWithArrayValue(Map first, Map second) { if (first.size() != second.size()) { return false; } return first.entrySet().stream() .allMatch(e -> Arrays.equals(e.getValue(), second.get(e.getKey()))); }

Contrairement à Map.equals () , notre propre méthode comparera avec succès HashMaps avec des valeurs de tableau:

@Test public void whenCompareTwoHashMapsWithArrayValuesUsingStreamAPI_thenSuccess() { assertTrue(areEqualWithArrayValue(asiaCity1, asiaCity2)); assertFalse(areEqualWithArrayValue(asiaCity1, asiaCity3)); }

4. Comparaison des clés et des valeurs HashMap

Ensuite, voyons comment comparer deux clés HashMap et leurs valeurs correspondantes.

4.1. Comparaison des clés HashMap

Tout d'abord, nous pouvons vérifier si deux HashMaps ont les mêmes clés en comparant simplement leur KeySet () :

@Test public void whenCompareTwoHashMapKeys_thenSuccess() { assertTrue(asiaCapital1.keySet().equals(asiaCapital2.keySet())); assertFalse(asiaCapital1.keySet().equals(asiaCapital3.keySet())); }

4.2. Comparaison des valeurs de HashMap

Ensuite, nous verrons comment comparer les valeurs HashMap une par une.

Nous allons implémenter une méthode simple pour vérifier quelles clés ont la même valeur dans les deux HashMaps à l' aide de l' API Stream :

private Map areEqualKeyValues(Map first, Map second) { return first.entrySet().stream() .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().equals(second.get(e.getKey())))); }

Nous pouvons maintenant utiliser areEqualKeyValues ​​() pour comparer deux HashMaps différents pour voir en détail quelles clés ont la même valeur et lesquelles ont des valeurs différentes:

@Test public void whenCompareTwoHashMapKeyValuesUsingStreamAPI_thenSuccess() { Map asiaCapital3 = new HashMap(); asiaCapital3.put("Japan", "Tokyo"); asiaCapital3.put("South Korea", "Seoul"); asiaCapital3.put("China", "Beijing"); Map asiaCapital4 = new HashMap(); asiaCapital4.put("South Korea", "Seoul"); asiaCapital4.put("Japan", "Osaka"); asiaCapital4.put("China", "Beijing"); Map result = areEqualKeyValues(asiaCapital3, asiaCapital4); assertEquals(3, result.size()); assertThat(result, hasEntry("Japan", false)); assertThat(result, hasEntry("South Korea", true)); assertThat(result, hasEntry("China", true)); }

5. Différence de carte en utilisant la goyave

Enfin, nous verrons comment obtenir une différence détaillée entre deux HashMaps en utilisant Guava Maps.difference ().

Cette méthode renvoie un objet MapDifference qui a un certain nombre de méthodes utiles pour analyser la différence entre les cartes. Jetons un coup d'œil à certains d'entre eux.

5.1. MapDifference.entriesDiffering ()

Tout d'abord, nous obtiendrons des clés communes qui ont des valeurs différentes dans chaque HashMap en utilisant MapDifference.entriesDiffering () :

@Test public void givenDifferentMaps_whenGetDiffUsingGuava_thenSuccess() { Map asia1 = new HashMap(); asia1.put("Japan", "Tokyo"); asia1.put("South Korea", "Seoul"); asia1.put("India", "New Delhi"); Map asia2 = new HashMap(); asia2.put("Japan", "Tokyo"); asia2.put("China", "Beijing"); asia2.put("India", "Delhi"); MapDifference diff = Maps.difference(asia1, asia2); Map
    
      entriesDiffering = diff.entriesDiffering(); assertFalse(diff.areEqual()); assertEquals(1, entriesDiffering.size()); assertThat(entriesDiffering, hasKey("India")); assertEquals("New Delhi", entriesDiffering.get("India").leftValue()); assertEquals("Delhi", entriesDiffering.get("India").rightValue()); }
    

La méthode entriesDiffering () renvoie une nouvelle Map qui contient l'ensemble des clés communes et des objets ValueDifference comme ensemble de valeurs.

Chaque objet ValueDifference a une méthode leftValue () et rightValue () qui renvoient respectivement les valeurs des deux cartes .

5.2. MapDifference.entriesOnlyOnRight () et MapDifference.entriesOnlyOnLeft ()

Ensuite, nous pouvons obtenir des entrées qui n'existent que dans un seul HashMap en utilisant MapDifference.entriesOnlyOnRight () et MapDifference.entriesOnlyOnLeft ():

@Test public void givenDifferentMaps_whenGetEntriesOnOneSideUsingGuava_thenSuccess() { MapDifference diff = Maps.difference(asia1, asia2); Map entriesOnlyOnRight = diff.entriesOnlyOnRight(); Map entriesOnlyOnLeft = diff.entriesOnlyOnLeft(); assertEquals(1, entriesOnlyOnRight.size()); assertEquals(1, entriesOnlyOnLeft.size()); assertThat(entriesOnlyOnRight, hasEntry("China", "Beijing")); assertThat(entriesOnlyOnLeft, hasEntry("South Korea", "Seoul")); }

5.3. MapDifference.entriesInCommon ()

Ensuite, nous obtiendrons des entrées communes en utilisant MapDifference.entriesInCommon ():

@Test public void givenDifferentMaps_whenGetCommonEntriesUsingGuava_thenSuccess() { MapDifference diff = Maps.difference(asia1, asia2); Map entriesInCommon = diff.entriesInCommon(); assertEquals(1, entriesInCommon.size()); assertThat(entriesInCommon, hasEntry("Japan", "Tokyo")); }

5.4. Personnalisation du comportement de Maps.difference ()

Puisque Maps.difference () utilise equals () et hashCode () par défaut pour comparer les entrées, cela ne fonctionnera pas pour les objets qui ne les implémentent pas correctement:

@Test public void givenSimilarMapsWithArrayValue_whenCompareUsingGuava_thenFail() { MapDifference diff = Maps.difference(asiaCity1, asiaCity2); assertFalse(diff.areEqual()); }

Mais, nous pouvons personnaliser la méthode utilisée en comparaison en utilisant Equivalence .

Par exemple, nous allons définir Equivalence pour le type String [] pour comparer les valeurs String [] dans nos HashMaps comme nous le souhaitons:

@Test public void givenSimilarMapsWithArrayValue_whenCompareUsingGuavaEquivalence_thenSuccess() { Equivalence eq = new Equivalence() { @Override protected boolean doEquivalent(String[] a, String[] b) { return Arrays.equals(a, b); } @Override protected int doHash(String[] value) { return value.hashCode(); } }; MapDifference diff = Maps.difference(asiaCity1, asiaCity2, eq); assertTrue(diff.areEqual()); diff = Maps.difference(asiaCity1, asiaCity3, eq); assertFalse(diff.areEqual()); }

6. Conclusion

Dans cet article, nous avons discuté de différentes façons de comparer les HashMaps en Java. Nous avons appris plusieurs façons de vérifier si deux HashMaps sont égaux et comment obtenir la différence détaillée.

Le code source complet est disponible à l'adresse over sur GitHub.