Reputation: 601
Looking for a standard library function way in Java for adding the values in two maps based on their keys.
Map A: {a=1, b=2}
Map B: {a=2, c=3}
Resulting map:
Map C: {a=3, b=2, c=3}
I know this can be coded in a few lines. I also know functional programming is great for this. I am just wandering if there is a standard function or syntax people use out there.
Something like (but probably more generic than):
public HashMap<String,Double> addValues(HashMap<String,Double> a, HashMap<String,Double> b) {
HashMap<String,Double> ret = new HashMap<String,Double>(a);
for (String s : b.keySet()) {
if (ret.containsKey(s)) {
ret.put(s, b.get(s) + ret.get(s));
} else {
ret.put(s, b.get(s));
}
}
return ret;
}
Upvotes: 6
Views: 8048
Reputation: 7555
Here's a version that allows for any number of Maps
to be combined:
public static Map<String, Integer> addKeys(Map<String, Integer>... maps) {
Set<String> keys = new HashSet<String>();
for (Map<String, Integer> map : maps)
keys.addAll(map.keySet());
Map<String, Integer> result = new HashMap<String, Integer>();
for (String key : keys) {
Integer value = 0;
for (Map<String, Integer> map : maps)
if (map.containsKey(key))
value += map.get(key);
result.put(key, value);
}
return result;
}
Usage:
public static void main(String[] args){
Map<String, Integer> a = new HashMap<String, Integer>();
a.put("a", 1);
a.put("b", 2);
Map<String, Integer> b = new HashMap<String, Integer>();
b.put("a", 2);
b.put("c", 3);
Map<String, Integer> c = addKeys(a, b);
System.out.println(c);
}
Ouptut:
{b=2, c=3, a=3}
Unfortunately, it's not possible as far as I can see to create a generic method:
public static <K, V extends Number> Map<K, V> addKeys(Class<V> cls, Map<K, V>... maps);
Because the Number
class doesn't support the +
operator. Which seems a bit daft to me...
Upvotes: 1
Reputation: 328618
An alternative which does essentially the same thing, using Java 8 new getOrDefault
method:
Set<String> keys = new HashSet<> (a.keySet());
keys.addAll(b.keySet());
Map<String, Integer> c = new HashMap<>();
for (String k : keys) {
c.put(k, a.getOrDefault(k, 0) + b.getOrDefault(k, 0));
}
But if using Java 8, you may as well stream the keys and make it a one liner:
Map<String, Object> c = Stream.concat(a.keySet().stream(), b.keySet().stream())
.distinct()
.collect(toMap(k -> k, k -> a.getOrDefault(k, 0) + b.getOrDefault(k, 0)));
Upvotes: 3