代码之家  ›  专栏  ›  技术社区  ›  Ori Marko

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

  •  3
  • Ori Marko  · 技术社区  · 6 年前

    我只需要找出两个映射之间的差异,而不同的映射可以通过缺少键或键的不同值来实现。

    我找到了一个普遍的答案 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 回复  |  直到 6 年前
        1
  •  2
  •   Eugene    6 年前

    嗯,你可以比较一下 Entry S来自A Map ,因为该类重写 equals/hashCode 以你想要的方式。不完全清楚您要保留哪些条目,哪些条目来自 左侧地图 右侧地图 或者他们中的任何一个。

    例如,这可以通过以下方式实现:

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

    另一方面,如果您只想保留第二个条目(右) 地图 :

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

    显然你需要 guava java-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()));
                    }
                });
    
        2
  •  1
  •   Olivier Grégoire    6 年前

    使用番石榴 Maps.difference(Map, Map) .

    Their wiki 解释它是如何工作的,但您可以在下面找到解决问题的方法。

    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}