1

I have two maps:

Map<String, Sample> newMap = convertJSONObjectToSampleMap(newMapStr);
Map<String, Sample> oldMap = convertJSONObjectToSampleMap(oldMapStr);

the Sample is some custom class

The newMap has keys: [1,2,3,4,5] The oldMap has keys: [2,3,4,5,8]

What is the best way to get difference between them, .e, get Samples with keys: 1 and 8?

I thought to use Collections and extract Set<>:

Set<String> newSet = newMap.keySet();
Set<String> oldSet = oldMap.keySet();

Thank you,

VH-NZZ
  • 5,248
  • 4
  • 31
  • 47
snaggs
  • 5,543
  • 17
  • 64
  • 127
  • see http://stackoverflow.com/questions/8064570/what-is-the-best-way-get-the-symmetric-difference-between-two-sets-in-java – Arturo Volpe May 03 '14 at 14:33

3 Answers3

6

What you want is called the symmetric difference.

enter image description here

Guava provides such a method.

Set<String> diff = Sets.symmetricDifference(newSet, oldSet);

Then just iterate through the set get the samples.

List<Sample> samples = new ArrayList<>();
for(String key : diff){
    if(oldMap.containsKey(key)){
        samples.add(oldMap.get(key));
    } else {
        samples.add(newMap.get(key));
    }
}

You can also do it with the official API, basically the symmetric difference is the union minus the intersection of both sets, but why reinvent the wheel?

Using an external dependency can be bad if you're using only one method, but Guava provides a lot of useful features that are a must.

Alexis C.
  • 91,686
  • 21
  • 171
  • 177
2

Loop through one map and compare.

It's only O(n) to loop through one of the maps. Consider this code:

for (String key: oldMap.keySet()) {
    if (newMap.containsKey(key))
        newMap.remove(key);
    else
        newMap.put(key, oldMap.get(key));
}

And the newMap will now contain only the unique entries from both sets. It gives you the keys and the values, so all the data is in one place. It's fast, because you only need to loop through the keys in one of the maps and you don't have to create sets.

Erick Robertson
  • 32,125
  • 13
  • 69
  • 98
2

Use a function like this if you're interested only on the keys:

public static Set<String> getDiff(Map<String,Object> mapA, Map<String,Object> mapB) {
    Set<String> diff = mapA.keySet();
    for (String s: mapB.keySet()) {
        if (diff.contains(s))
            diff.remove(s);
        else
            diff.add(s);
    }
    return diff;
}

Use the following function for the full diff Map (without affecting your existing Map objects):

public static Map<String,Object> getDiff(Map<String,Object> mapA, Map<String,Object> mapB) {
   Map<String,Object> diff = new HashMap<String,Object>();
   diff.putAll(mapA);
   for (String s: mapB.keySet()) {
       if (diff.containsKey(s))
           diff.remove(s);
       else
           diff.put(s, mapB.get(s));
   }
   return diff;
}
Kostas Kryptos
  • 4,081
  • 2
  • 23
  • 24