Merging 2 HashMaps in Java

2020-05-07 11:09发布

问题:

I have a program that needs to merge two HashMap. The hashmaps have a key that is a String and a value that is an Integer. The special condition of the merge is that if the key is already in the dictionary, the Integer needs to be added to the existing value and not replace it. Here is the code I have so far that is throwing a NullPointerException.

public void addDictionary(HashMap<String, Integer> incomingDictionary) {
        for (String key : incomingDictionary.keySet()) {
            if (totalDictionary.containsKey(key)) {
                Integer newValue = incomingDictionary.get(key) + totalDictionary.get(key);
                totalDictionary.put(key, newValue);
            } else {
                totalDictionary.put(key, incomingDictionary.get(key));
            }
        }
    }

回答1:

If your code cannot guarantee that incomingDictionary will be initialized before it reaches this method, you will have to do a null check, no way out

public void addDictionary(HashMap<String, Integer> incomingDictionary) {
    if (incomingDictionary == null) {
        return; // or throw runtime exception
    }
    if (totalDictionary == null) {
        return;// or throw runtime exception
    }
    if (totalDictionary.isEmpty()) {
        totalDictionary.putAll(incomingDictionary);
    } else {
        for (Entry<String, Integer> incomingIter : incomingDictionary.entrySet()) {
            String incomingKey = incomingIter.getKey();
            Integer incomingValue = incomingIter.getValue();
            Integer totalValue = totalDictionary.get(incomingKey);
            // If total dictionary contains null for the incoming key it is
            // as good as replacing it with incoming value.
            Integer sum = (totalValue == null ? 
                                            incomingValue : incomingValue == null ? 
                                                    totalValue : totalValue + incomingValue
                          );
            totalDictionary.put(incomingKey, sum);
        }
    }
}

Considering HashMap allows null as value another place in your code which is prone to NPE is

Integer newValue = incomingDictionary.get(key) + totalDictionary.get(key);

if either of these two is null you will get NPE.



回答2:

you have probably one of your dictionnaries not initialized. Here is one solution:

public void addDictionary(HashMap<String, Integer> incomingDictionary) {
    if (incomingDictionary == null) {
        throw new IllegalArgumentException("incomingDictionary cannot be null.");
    }
    if (totalDictionary == null) {
        throw new IllegalArgumentException("totalDictionary cannot be null.");
        // or another solution:
        // totalDictionary = new HashMap<String, Integer>();
        // totalDictionary.putAll(incomingDictionary);
        // return;
    }

    for (Map.Entry<String, Integer> entry : incomingDictionary.entrySet()) {
        Integer oldValue = totalDictionary.get(entry.getKey());
        if (oldValue != null){
            // here entry.getValue() could be null!
            // Never put a null value in your Map, or add a test here
            Integer newValue = entry.getValue() + oldValue;
            totalDictionary.put(entry.getKey(), newValue);
        } else {
            totalDictionary.put(entry.getKey(), entry.getValue());
        }
    }
}


回答3:

Considering that totalDictionary are correctly initialized, in:

Integer newValue = incomingDictionary.get(key) + totalDictionary.get(key);

totalDictionary.get(key) could not return null.
Maybe you need to add something like this before:

if(totalDictionary.get(key) == null)
  totalDictionary.put(key, 0);