Java包括值的地图之间的差异

时间:2018-05-22 11:03:52

标签: java

我只需要找到两张地图之间的差异,而不同的可能是缺少密钥或密钥的不同值。

我找到了Differences between maps

的一般答案
sources.removeAll(targets) ... leaves only entries in sources that are only in sources, not in target
     

,而

sources.retainAll(targets) ... leaves only entries that are in both sets

但我不确定它是否比下面的代码更好,因为我需要检查密钥存在,以及值是不同的

    Map<K, V> updatedMap = new EnumMap<>(K.class);
    for (Map.Entry<K, V> finalSet : secondMap.entrySet()) {
        K currentKey = finalSet.getKey();
        if (!firstMap.containsKey(currentKey) || firstMap.get(currentKey) != finalSet.getValue()) {
            updatedMap.put(currentKey, finalSet.getValue());
            firstMap.remove(currentKey);
        }
    }
    for (Map.Entry<K, V> currentSet : firstMap.entrySet()) {
        K currentKey = currentSet.getKey();
        if (!secondMap.containsKey(currentKey)) {
            updatedMap.put(currentKey, currentSet.getValue());
        } else if (secondMap.get(currentKey) != currentSet.getValue()) {
            updatedMap.put(currentKey, secondMap.get(currentKey));
        }
    }

他们是更好的方法来找到包括值的地图之间的差异吗?

2 个答案:

答案 0 :(得分:2)

好吧,您可以比较Entry中的Map,因为该类会以您想要的方式覆盖equals/hashCode。您不想完全清楚哪些条目要保留,左侧地图右侧地图或其中任何条目。

例如,这可以通过以下方式完成:

Map<Integer, String> allDifs = 
             Sets.symmetricDifference(left.entrySet(), right.entrySet())
                 .stream()
                 .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

另一方面,如果您只想将条目保留在第二个(右侧)Map

 Map<Integer, String> result = 
             Sets.difference(right.entrySet(), left.entrySet())
                 .stream()
                 .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

    System.out.println(result); 

显然,您需要guavajava-8 ...

修改

使用Collectors.toMap无法实现您真正想要的内容,但您可以使用以下内容实现:

    Map<Integer, String> result = new HashMap<>();
    Sets.symmetricDifference(right.entrySet(), left.entrySet())
            .stream()
            .forEachOrdered(x -> {
                String previousValue = result.putIfAbsent(x.getKey(), x.getValue());
                if (previousValue != null) {
                    result.replace(x.getKey(), right.get(x.getKey()));
                }
            });

答案 1 :(得分:1)

使用Guava&#39; GetAtt intrinsic function

Maps.difference(Map, Map)解释了它的工作原理,但您可以在下面找到解决问题的方法。

Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
Map<String, Integer> right = ImmutableMap.of("b", 2, "c", 4, "d", 5);
MapDifference<String, Integer> diff = Maps.difference(left, right);

Map<String, Integer> output = new HashMap<>();
output.putAll(diff.entriesOnlyOnLeft());
output.putAll(diff.entriesOnlyOnRight());
for (Map.Entry<String,MapDifference.ValueDifference<Integer>> e: diff.entriesDiffering().entrySet()) {
  // Java 10 and later : for (var e: diff.entriesDiffering().entrySet())
  output.put(e.getKey(), e.getValue().rightValue());
}
System.out.println(output); // {a=1, c=4, d=5}