用Java比較兩個HashMap

1.概述

在本教程中,我們將探索在Java中比較兩個HashMaps不同方法

我們將討論多種方法來檢查兩個HashMaps是否相似。我們還將使用Java 8 Stream API和Guava來獲取不同HashMaps之間的詳細區別。

2.使用Map.equals()

首先,我們將使用Map.equals()檢查兩個HashMaps是否具有相同的條目:

@Test

 public void whenCompareTwoHashMapsUsingEquals_thenSuccess() {

 Map<String, String> asiaCapital1 = new HashMap<String, String>();

 asiaCapital1.put("Japan", "Tokyo");

 asiaCapital1.put("South Korea", "Seoul");



 Map<String, String> asiaCapital2 = new HashMap<String, String>();

 asiaCapital2.put("South Korea", "Seoul");

 asiaCapital2.put("Japan", "Tokyo");



 Map<String, String> asiaCapital3 = new HashMap<String, String>();

 asiaCapital3.put("Japan", "Tokyo");

 asiaCapital3.put("China", "Beijing");



 assertTrue(asiaCapital1.equals(asiaCapital2));

 assertFalse(asiaCapital1.equals(asiaCapital3));

 }

在這裡,我們正在創建三個HashMap對象並添加條目。然後,我們使用Map.equals()檢查兩個HashMaps是否具有相同的條目。

Map.equals()工作方式是使用**Object.equals()**方法**比較鍵和值**.這意味著它僅在鍵和值對像都正確實現equals()時才起作用。

例如,當值類型為array時, Map.equals()不起作用,因為數組的equals()方法將比較標識而不是數組的內容:

@Test

 public void whenCompareTwoHashMapsWithArrayValuesUsingEquals_thenFail() {

 Map<String, String[]> asiaCity1 = new HashMap<String, String[]>();

 asiaCity1.put("Japan", new String[] { "Tokyo", "Osaka" });

 asiaCity1.put("South Korea", new String[] { "Seoul", "Busan" });



 Map<String, String[]> asiaCity2 = new HashMap<String, String[]>();

 asiaCity2.put("South Korea", new String[] { "Seoul", "Busan" });

 asiaCity2.put("Japan", new String[] { "Tokyo", "Osaka" });



 assertFalse(asiaCity1.equals(asiaCity2));

 }

3.使用Java Stream API

我們還可以使用Java 8 Stream API實現自己的方法來比較HashMaps

private boolean areEqual(Map<String, String> first, Map<String, String> second) {

 if (first.size() != second.size()) {

 return false;

 }



 return first.entrySet().stream()

 .allMatch(e -> e.getValue().equals(second.get(e.getKey())));

 }

為簡單起見,我們實現了areEqual()方法,該方法現在可用於比較HashMap<String, String>對象:

@Test

 public void whenCompareTwoHashMapsUsingStreamAPI_thenSuccess() {

 assertTrue(areEqual(asiaCapital1, asiaCapital2));

 assertFalse(areEqual(asiaCapital1, asiaCapital3));

 }

但是我們還可以通過使用Arrays.equals()比較兩個數組來定制自己的方法areEqualWithArrayValue()來處理數組值:

private boolean areEqualWithArrayValue(Map<String, String[]> first, Map<String, String[]> second) {

 if (first.size() != second.size()) {

 return false;

 }



 return first.entrySet().stream()

 .allMatch(e -> Arrays.equals(e.getValue(), second.get(e.getKey())));

 }

Map.equals()不同,我們自己的方法將成功比較HashMaps與數組值:

@Test

 public void whenCompareTwoHashMapsWithArrayValuesUsingStreamAPI_thenSuccess() {

 assertTrue(areEqualWithArrayValue(asiaCity1, asiaCity2));

 assertFalse(areEqualWithArrayValue(asiaCity1, asiaCity3));

 }

4.比較HashMap鍵和值

接下來,讓我們看看如何比較兩個HashMap鍵及其對應的值。

4.1。比較HashMap

首先,我們可以通過比較兩個HashMapsKeySet()來檢查它們是否具有相同的鍵:

@Test

 public void whenCompareTwoHashMapKeys_thenSuccess() {

 assertTrue(asiaCapital1.keySet().equals(asiaCapital2.keySet()));

 assertFalse(asiaCapital1.keySet().equals(asiaCapital3.keySet()));

 }

4.2。比較HashMap

接下來,我們將看到如何一個一個地比較HashMap值。

我們將實現一個簡單的方法,使用Stream API檢查兩個HashMaps哪些鍵的值相同:

private Map<String, Boolean> areEqualKeyValues(Map<String, String> first, Map<String, String> second) {

 return first.entrySet().stream()

 .collect(Collectors.toMap(e -> e.getKey(),

 e -> e.getValue().equals(second.get(e.getKey()))));

 }

現在,我們可以使用areEqualKeyValues()比較兩個不同的HashMaps ,以詳細查看哪些鍵具有相同的值,以及哪些鍵具有不同的值:

@Test

 public void whenCompareTwoHashMapKeyValuesUsingStreamAPI_thenSuccess() {

 Map<String, String> asiaCapital3 = new HashMap<String, String>();

 asiaCapital3.put("Japan", "Tokyo");

 asiaCapital3.put("South Korea", "Seoul");

 asiaCapital3.put("China", "Beijing");



 Map<String, String> asiaCapital4 = new HashMap<String, String>();

 asiaCapital4.put("South Korea", "Seoul");

 asiaCapital4.put("Japan", "Osaka");

 asiaCapital4.put("China", "Beijing");



 Map<String, Boolean> 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.使用番石榴映射差異

最後,我們將看到如何使用Guava Maps.difference().獲得兩個HashMaps之間的詳細區別Maps.difference().

此方法返回一個MapDifference對象,該對象具有許多有用的方法來分析Maps.之間的差異Maps.讓我們來看看其中的一些。

5.1。 MapDifference.entriesDiffering()

首先,我們將使用MapDifference.entriesDiffering()在每個HashMap**獲得具有不同值的通用鍵**:

@Test

 public void givenDifferentMaps_whenGetDiffUsingGuava_thenSuccess() {

 Map<String, String> asia1 = new HashMap<String, String>();

 asia1.put("Japan", "Tokyo");

 asia1.put("South Korea", "Seoul");

 asia1.put("India", "New Delhi");



 Map<String, String> asia2 = new HashMap<String, String>();

 asia2.put("Japan", "Tokyo");

 asia2.put("China", "Beijing");

 asia2.put("India", "Delhi");



 MapDifference<String, String> diff = Maps.difference(asia1, asia2);

 Map<String, ValueDifference<String>> 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());

 }

entriesDiffering()方法返回一個新Map ,該Map包含一組公用鍵和ValueDifference對像作為一組值。

每個ValueDifference像都有一個leftValue()rightValue()方法,分別返回兩個Maps的值

5.2。 MapDifference.entriesOnlyOnRight()MapDifference.entriesOnlyOnLeft()

然後,我們可以使用MapDifference.entriesOnlyOnRight()MapDifference.entriesOnlyOnLeft():獲得僅存在於一個HashMap條目MapDifference.entriesOnlyOnLeft():

@Test

 public void givenDifferentMaps_whenGetEntriesOnOneSideUsingGuava_thenSuccess() {

 MapDifference<String, String> diff = Maps.difference(asia1, asia2);

 Map<String, String> entriesOnlyOnRight = diff.entriesOnlyOnRight();

 Map<String, String> 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()

接下來,我們將使用MapDifference.entriesInCommon():獲得常見條目MapDifference.entriesInCommon():

@Test

 public void givenDifferentMaps_whenGetCommonEntriesUsingGuava_thenSuccess() {

 MapDifference<String, String> diff = Maps.difference(asia1, asia2);

 Map<String, String> entriesInCommon = diff.entriesInCommon();



 assertEquals(1, entriesInCommon.size());

 assertThat(entriesInCommon, hasEntry("Japan", "Tokyo"));

 }

5.4。自定義Maps.difference()行為

由於Maps.difference()默認情況下使用equals()hashCode()來比較條目,因此不適用於未正確實現它們的對象:

@Test

 public void givenSimilarMapsWithArrayValue_whenCompareUsingGuava_thenFail() {

 MapDifference<String, String[]> diff = Maps.difference(asiaCity1, asiaCity2);

 assertFalse(diff.areEqual());

 }

但是,我們可以使用Equivalence定制用於比較的方法

例如,我們將為String[]類型定義Equivalence ,以根據需要在HashMaps比較String[]值:

@Test

 public void givenSimilarMapsWithArrayValue_whenCompareUsingGuavaEquivalence_thenSuccess() {

 Equivalence<String[]> eq = new Equivalence<String[]>() {

 @Override

 protected boolean doEquivalent(String[] a, String[] b) {

 return Arrays.equals(a, b);

 }



 @Override

 protected int doHash(String[] value) {

 return value.hashCode();

 }

 };



 MapDifference<String, String[]> diff = Maps.difference(asiaCity1, asiaCity2, eq);

 assertTrue(diff.areEqual());



 diff = Maps.difference(asiaCity1, asiaCity3, eq);

 assertFalse(diff.areEqual());

 }

六,結論

在本文中,我們討論了在Java中比較HashMaps不同方法。我們學習了多種方法來檢查兩個HashMaps是否相等以及如何獲取詳細的差異。

完整的源代碼可在GitHub上獲得