Java 映射之间的差异,包括值



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

我找到了地图之间差异的一般答案

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));
}
}

它们是查找地图(包括值(之间差异的更好方法吗?

好吧,你可以比较MapEntry,因为该类以你想要的方式覆盖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()));
}
});

使用 Guava 的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}

最新更新