Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Differences between maps including values

Tags:

java

I need to find only differences between 2 maps, while the different can be by missing key or by different value for key.

I find a general answer for Differences between maps

sources.removeAll(targets) ... leaves only entries in sources that are only in sources, not in target

whereas

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

But I'm not sure it's better than the following code, because I need to check apart from key existence also that the values are different

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

Is their a better way of finding the differences between maps including values?

like image 899
user7294900 Avatar asked Oct 17 '25 15:10

user7294900


1 Answers

Well, you could compare Entrys from a Map, because that class overrides equals/hashCode in the manner that you want. It's not entirely clear which entries you would want to keep, the ones from the left map or the right map or any of them.

For example this could be done via :

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

On the other hand if you just want to keep entries form the second (right) Map:

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

    System.out.println(result); 

Obviously you need guava and java-8 for this...

EDIT

what you actually want is not achievable with Collectors.toMap, but you can do it with:

    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()));
                }
            });
like image 102
Eugene Avatar answered Oct 22 '25 04:10

Eugene