Vergleichen von zwei HashMaps in Java

1. Übersicht

In diesem Tutorial werden wir verschiedene Möglichkeiten untersuchen, um zwei HashMaps in Java zu vergleichen .

Wir werden verschiedene Möglichkeiten diskutieren, um zu überprüfen, ob zwei HashMaps ähnlich sind. Wir werden auch Java 8 Stream API und Guava verwenden, um die detaillierten Unterschiede zwischen verschiedenen HashMaps zu ermitteln .

2. Verwenden von Map.equals ()

Zuerst verwenden wir Map.equals () , um zu überprüfen, ob zwei HashMaps dieselben Einträge haben:

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

Hier erstellen wir drei HashMap- Objekte und fügen Einträge hinzu. Dann verwenden wir Map.equals () , um zu überprüfen, ob zwei HashMaps dieselben Einträge haben.

Die Art und Weise , dass Map.equals () funktioniert , ist durch Verwendung von Schlüsseln und Werten des Vergleich Object.equals () Methode . Dies bedeutet, dass es nur funktioniert, wenn sowohl Schlüssel- als auch Wertobjekte equals () ordnungsgemäß implementieren .

Zum Beispiel funktioniert Map.equals () nicht, wenn der Werttyp Array ist, da die equals () -Methode eines Arrays die Identität und nicht den Inhalt des Arrays vergleicht:

@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. Verwenden der Java Stream- API

Wir können auch unsere eigene Methode implementieren, um HashMaps mithilfe der Java 8 Stream- API zu vergleichen :

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

Der Einfachheit halber haben wir die areEqual () -Methode implementiert, mit der wir jetzt HashMap- Objekte vergleichen können:

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

Wir können aber auch unsere eigene Methode areEqualWithArrayValue () anpassen , um Array-Werte zu verarbeiten, indem wir Arrays.equals () verwenden , um zwei Arrays zu vergleichen:

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

Im Gegensatz zu Map.equals () vergleicht unsere eigene Methode HashMaps erfolgreich mit Array-Werten:

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

4. Vergleichen von HashMap- Schlüsseln und -Werten

Als nächstes wollen wir sehen, wie zwei HashMap- Schlüssel und ihre entsprechenden Werte verglichen werden.

4.1. Im Vergleich HashMap Keys

Zunächst können wir überprüfen, ob zwei HashMaps dieselben Schlüssel haben, indem wir nur ihr KeySet () vergleichen :

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

4.2. Vergleicht man HashMap Werte

Als nächstes sehen wir, wie HashMap- Werte einzeln verglichen werden.

Wir implementieren eine einfache Methode, um mithilfe der Stream- API zu überprüfen, welche Schlüssel in beiden HashMaps denselben Wert haben :

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

Wir können jetzt areEqualKeyValues ​​() verwenden , um zwei verschiedene HashMaps zu vergleichen und im Detail zu sehen, welche Schlüssel denselben Wert und welche unterschiedliche Werte haben:

@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. Kartenunterschied mit Guave

Schließlich werden wir sehen, wie Sie mit Guava Maps.difference () einen detaillierten Unterschied zwischen zwei HashMaps ermitteln.

Diese Methode gibt ein MapDifference- Objekt zurück, das über eine Reihe nützlicher Methoden verfügt, um den Unterschied zwischen den Maps zu analysieren . Schauen wir uns einige davon an.

5.1. MapDifference.entriesDiffering ()

Zuerst erhalten wir mit MapDifference.entriesDiffering () gemeinsame Schlüssel, die in jeder HashMap unterschiedliche Werte haben :

@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()); }
    

Die Methode entryDiffering () gibt eine neue Map zurück , die den Satz allgemeiner Schlüssel und ValueDifference- Objekte als Satz von Werten enthält.

Jedes ValueDifference- Objekt verfügt über die Methoden leftValue () und rightValue () , die die Werte in den beiden Maps zurückgeben .

5.2. MapDifference.entriesOnlyOnRight () und MapDifference.entriesOnlyOnLeft ()

Dann können wir mit MapDifference.entriesOnlyOnRight () und MapDifference.entriesOnlyOnLeft () Einträge abrufen , die nur in einer HashMap vorhanden sind :

@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 ()

Als Nächstes erhalten wir allgemeine Einträge mit 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. Anpassen des Verhaltens von Maps.difference ()

Da Maps.difference () Verwendung equals () und hashCode () durch Standardeinträge vergleichen zu können , wird es nicht funktioniert für Objekte , die sie nicht richtig implementieren:

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

Aber können wir das Verfahren im Vergleich verwendet , um anpassen Equivalence .

Zum Beispiel definieren wir die Äquivalenz für den Typ String [] , um die Werte von String [] in unseren HashMaps nach Belieben zu vergleichen :

@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. Fazit

In diesem Artikel haben wir verschiedene Möglichkeiten zum Vergleichen von HashMaps in Java erläutert . Wir haben mehrere Möglichkeiten kennengelernt , um zu überprüfen, ob zwei HashMaps gleich sind und wie der detaillierte Unterschied ermittelt werden kann.

Der vollständige Quellcode ist auf GitHub verfügbar.