Java中如何比较两个Map

培训教学 潘老师 7个月前 (10-11) 305 ℃ (0) 扫码查看

学习在Java中比较两个HashMap的不同方式,包括按键、值和键值对比较。还学习如何在允许或限制重复值的情况下比较Map。

1.比较具有相同键和值的Map

1.1. 使用Map.equals()

默认情况下,HashMap.equals()方法通过键值对比较两个HashMap。这意味着两个HashMap实例必须具有完全相同的键值对,且大小相同。键值对的顺序可以不同,不影响比较。

Map<String, Integer> map1 = Map.of("A", 1, "B", 2);
Map<String, Integer> map2 = Map.of("A", 1, "B", 2);
Map<String, Integer> map3 = Map.of("C", 1, "D", 2);
Assertions.assertTrue( map1.equals(map2) );
Assertions.assertFalse( map1.equals(map3) );

1.2. 比较具有数组类型值的Map

值得注意的是,Map的键和值是使用它们的equals()方法进行比较的,因此键和值对象必须正确实现equals()方法以获得一致的结果。例如,如果Map的值是数组,那么比较将不起作用,因为array.equals()比较的是对象标识,而不是数组的内容。

Map<String, Integer[]> map4 = Map.of("A", new Integer[]{1}, "B", new Integer[]{2});
Map<String, Integer[]> map5 = Map.of("A", new Integer[]{1}, "B", new Integer[]{2});
Assertions.assertFalse(map4.equals(map5));

在这种情况下,我们可以创建一个自定义方法,使用Arrays.equals()方法来比较数组内容。

private static boolean checkEqualMapsWithArrayTypeValues(
    Map<String, Integer[]> firstMap,
    Map<String, Integer[]> secondMap) {
  if (firstMap.size() != secondMap.size())
    return false;
  return firstMap.entrySet().stream()
      .allMatch(e -> Arrays.equals(e.getValue(), secondMap.get(e.getKey())));
}

现在Map比较将检查数组内容并给出正确的结果。

Map<String, Integer[]> map4 = Map.of("A", new Integer[]{1}, "B", new Integer[]{2});
Map<String, Integer[]> map5 = Map.of("A", new Integer[]{1}, "B", new Integer[]{2});
Assertions.assertFalse( checkEqualMapsWithArrayTypeValues(map4, map5) );

2.比较Map的键

我们可以比较两个Map是否具有相同的键,或者如果需要,可以找出第二个Map中缺失的键。

2.1. 两个Map具有相同的键

如果我们想按键比较HashMap,即如果两个HashMap具有完全相同的键集,则它们将相等,我们可以使用HashMap.keySet()函数。它返回一个包含所有映射键的HashSet。然后,我们可以使用Set.equals()方法来比较两个Map的HashSet。如果两个集合具有相同的大小,并且每个指定集合的元素都包含在另一个集合中,则它返回true。

Map<String, Integer> map1 = Map.of("A", 1, "B", 2);
Map<String, Integer> map2 = Map.of("A", 1, "B", 2);
Assertions.assertTrue( map1.keySet().equals(map2.keySet()) );
Map<String, Integer> map3 = Map.of("A", 1, "B", 2, "C", 3, "D", 4);
Assertions.assertFalse( map1.keySet().equals(map6.keySet()) );

2.2. Map键的差异

我们可能对找出第一个HashMap比第二个HashMap多出哪些键感兴趣。要获取这个差异,可以合并两个HashMap的键,然后删除在第一个HashMap中存在的所有键。通过Java程序来找出两个HashMap之间的差异。

HashSet<String> unionKeys = new HashSet<>(map1.keySet());
unionKeys.addAll(map3.keySet());
unionKeys.removeAll(map1.keySet());
Assertions.assertEquals(Set.of("C", "D"), unionKeys );

3.比较Map的值

如果我们想按值比较HashMap,即如果两个HashMap具有完全相同的值集,则它们将相等。请注意,HashMap允许重复的值,因此请确定是否要比较带有重复值或不带重复值的HashMap。

3.1. 不允许重复值

将HashMap.values()中的所有值添加到两个Map的ArrayList中。现在比较这两个ArrayList是否相等。

new ArrayList<>( map1.values() ).equals(new ArrayList<>( map2.values() ));       //true
new ArrayList<>( map1.values() ).equals(new ArrayList<>( map3.values() ));       //false

3.2. 允许重复值

如果要在比较HashMap之前删除重复值,将所有值添加到自动忽略重复值的HashSet中。

new HashSet<>( map1.values() ).equals(new HashSet<>( map2.values() ));  //true
new HashSet<>( map1.values() ).equals(new HashSet<>( map3.values() ));  //true

4.使用Guava进行Map的差异比较

如果我们想要找到两个Map之间的差异,Guava提供了一个出色的API Maps.difference()。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency>

Map.difference()返回一个MapDifference类的实例。通过检查MapDifference,我们可以以多种方式找到Map之间的差异。

MapDifference diff = Maps.difference(map1, map2);

让我们通过一个简单的示例看看API的工作方式。map1和map2都有一些共同的条目,而每个Map都有一些不同的条目。

Map<String, Integer> map1 = Map.of("A", 1, "B", 2, "E", 5, "F", 6);
Map<String, Integer> map2 = Map.of("A", 1, "B", 2, "C", 3, "D", 4);
MapDifference<String, Integer> diff = Maps.difference(map1, map2);
Assertions.assertFalse(diff.areEqual());
Assertions.assertEquals(Map.of("A", 1, "B", 2), diff.entriesInCommon());
Assertions.assertEquals(Map.of("E", 5, "F", 6), diff.entriesOnlyOnLeft());
Assertions.assertEquals(Map.of("C", 3, "D", 4), diff.entriesOnlyOnRight());

5.结论

在这个简短的教程中,我们学习了如何比较两个Map的条目、键和值的相等性。我们还学习了如何使用纯Java API以及Guava的MapDifference API来查找Map的差异。

如果您有与Java中比较HashMap相关的问题,请随时提出。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/teach/9443.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】