如何在java中获取地图的差异?

我有两张地图:

Map map1; Map map2; 

我需要收到这些地图之间的差异。 是否存在可能是apache utils如何获得这种差异? 现在似乎需要获取每个地图的入口集,发现diff1 = set1 – set2和diff2 = set2- set1。 创建汇总map = diff1 + diff2之后看起来非常笨拙。 是否存在另一种方式? 谢谢。

谷歌番石榴怎么样?:

 Maps.difference(map1,map2) 

这是一个简单的代码片段,您可以使用它而不是大量的Guava库:

 public static  Map mapDifference(Map left, Map right) { Map difference = new HashMap<>(); difference.putAll(left); difference.putAll(right); difference.entrySet().removeAll(right.entrySet()); return difference; } 

查看整个工作示例

如果我理解得很好,你试图计算两个地图入口集之间的对称差异 。

 Map map1; Map map2; Set> diff12 = new HashSet>(map1.entrySet()); Set> diff21 = new HashSet>(map2.entrySet()); Set> result; diff12.removeAll(map2.entrySet()); diff21.removeAll(map1.entrySet()); diff12.addAll(diff21); 

考虑到你提到的尴尬行为,让我们仔细看看上面的代码行为。 例如,如果我们从上面给出的链接中获取数值示例:

 Map map1 = new HashMap(); map1.put("a", 1); map1.put("b", 2); map1.put("c", 3); map1.put("d", 4); Map map2 = new HashMap(); map2.put("a", 1); map2.put("d", 4); map2.put("e", 5); 

在计算出差异后,输出如下:

 System.out.println(Arrays.deepToString(diff12.toArray())); 

得到:

 [e=5, c=3, b=2] 

这是正确的结果。 但是,如果我们这样做:

 public class CustomInteger { public int val; public CustomInteger(int val) { this.val = val; } @Override public String toString() { return String.valueOf(val); } } map1.put("a", new CustomInteger(1)); map1.put("b", new CustomInteger(2)); map1.put("c", new CustomInteger(3)); map1.put("d", new CustomInteger(4)); map2.put("a", new CustomInteger(1)); map2.put("d", new CustomInteger(4)); map2.put("e", new CustomInteger(5)); 

相同的算法给出以下输出:

 [e=5, a=1, d=4, d=4, b=2, a=1, c=3] 

这是不正确的(可能被描述为尴尬:))

在第一个示例中,地图填充了int值,这些值将自动装箱为Integer值。

Integer类有自己的equals和hashCode方法实现。

CustomInteger类不实现这些方法,因此它从无所不在的Object类 inheritance它们。

Set接口中 removeAll方法的API文档说明如下:

从此集合中删除指定集合中包含的所有元素(可选操作)。 如果指定的集合也是一个集合,则此操作会有效地修改此集合,以使其值为两个集合的不对称集合差异。

为了确定两个集合中包含哪些元素,removeAll方法使用集合元素的equals方法。

这就是问题:如果两个数值相同,则Integer的equals方法返回true,而Object的equals方法只有在相同的对象时才返回true,例如:

 Integer a = 1; //autoboxing Integer b = new Integer(1); Integer c = 2; a.equals(b); // true a.equals(c); // false CustomInteger d = new CustomInteger(1); CustomInteger e = new CustomInteger(1); CustomInteger f = new CustomInteger(2); d.equals(e); //false d.equals(f) // false d.val == e.val //true d.val == f.val //false 

如果它仍然有点模糊,我强烈建议阅读以下教程:

  • 学习Java语言
  • 集合
  Set> diff = new HashSet>((map1.entrySet())); diff.addAll(map2.entrySet());//Union Set> tmp = new HashSet>((map1.entrySet())); tmp.retainAll(map2.entrySet());//Intersection diff.removeAll(tmp);//Diff 

Google Collections Library了一个MapDifference API,它公开了以下方法:

  boolean areEqual() 

如果两个映射之间没有差异,则返回true; 也就是说,如果地图相同。

  Map> entriesDiffering() 

返回一个不可修改的映射,描述出现在两个映射中但具有不同值的键。

  Map entriesInCommon() 

返回包含两个映射中显示的条目的不可修改的映射; 也就是两张地图的交点。

以弗拉德的例子为基础,使用不同大小的地图

 public static  Map mapDiff(Map left, Map right) { Map difference = new HashMap<>(); difference.putAll(left); difference.putAll(right); difference.entrySet().removeAll(left.size() <= right.size() ? left.entrySet() : right.entrySet()); return difference; } 

尝试使用guava的MapDifference 。