Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing key and values of two java maps

I'm still relatively new to Java and I'm finding myself stuck on trying to properly write this piece of code that I feel should be a bit more simple.

I have two maps made up of two different instances of the same object. The keys are objects, and the values are objects.

There are two instances because I'm trying to determine if the keys in one instance are different from the keys in another instance. I'm trying to specifically locate new keys or missing keys, and then compare the values of the keys which exist in both maps.

The sample code below is just to help visualize what I'm trying to do (hopefully it's not more confusing!)

The goal of the below example should tell me that key "C" is missing and there is a new key ("D") and then it should finally compare the values of keys in both maps.

Main question is, is there anyway to do this in one loop? Primarily because my actual code will touch the file system for the values in the map and I'm trying to minimize the times it has to touch the disk

Map<objA, objB> mapA = new HashMap<objA, objB>();
mapA.put("A", "1");
mapA.put("B", "2");
mapA.put("C", "3");

Map<objA, objB> mapB = new HashMap<objA, objB>();
mapB.put("A", "1");
mapB.put("D", "4");

// Check if something is missing from mapB
for(Map.Entry<objA, objB> entryMapA:mapA.entrySet())
{
    if(!mapB.containsKey(entryMapA.getKey())
        {
            System.out.println(entryMapA.getKey() + " is missing");
        }
}

// Check if something is new is in mapB
for(Map.Entry<objA, objB> entryMapB:mapB.entrySet())
{
    if(!mapA.containsKey(entryMapB.getKey())
    {  
        System.out.println(entryMapB.getKey() + " is new");
    }
}
like image 358
hax0r_n_code Avatar asked Dec 16 '22 15:12

hax0r_n_code


2 Answers

Keys in a Map are Sets, so you can use sets and the available operations on them.

For instance:

Set<String> keysInA = new HashSet<String>(mapA.keySet());
Set<String> keysInB = new HashSet<String>(mapB.keySet());

// Keys in A and not in B
Set<String> inANotB = new HashSet<String>(keysInA);
inANotB.removeAll(keysInB);

// Keys common to both maps
Set<String> commonKeys = new HashSet<String>(keysInA);
commonKeys.retainAll(keysInB);

etc etc.

Note: you MUST NOT use the key set of a map directly. If you do:

// This returns the actual key set of the map, NOT a copy!
Set<String> inANotB = mapA.keysSet();
inANotB.removeAll(mapB.keySet())

you actually remove the keys (and their associated values) in mapA.

Finally, you should note that HashSet makes no order guarantee. If this matters to you, you want to look at implementations of SortedSet (such as TreeSet).

like image 94
fge Avatar answered Jan 30 '23 17:01

fge


You may subtract the the keysets:

Set<objA> keysA1 = new HashSet<objA>(mapA.keySet()); // deepcopy
Set<objA> keysA2 = new HashSet<objA>(mapA.keySet()); // deepcopy
Set<objB> keysB = new HashSet<objB>(mapB.keySet()); // deepcopy

keysA1.removeAll(keysB);
keysB.removeAll(keysA2);

System.out.println("Missing in A: " + keysB);
System.out.println("Missing in B: " + keysA1);
like image 41
Jiri Kremser Avatar answered Jan 30 '23 16:01

Jiri Kremser