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