用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
鍵
首先,我們可以通過比較兩個HashMaps
的KeySet()
來檢查它們是否具有相同的鍵:
@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上獲得。