6

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;
  }

4
  • This should help you... docs.oracle.com/javase/7/docs/api/java/util/Set.html Commented Jul 1, 2014 at 14:59
  • 2
    Which datastructure you have? In Question you write Set, but you add map tag Commented Jul 1, 2014 at 15:02
  • Sorry Jens I meant maps, corrected now. Commented Jul 1, 2014 at 15:04
  • 1
    It would make your question easier to understand if you replaced Set by Map. In Java 7 there is no standard method to do this, since it really needs a function argument to combine the values, and that's ugly w/o closures. Maybe it's somewhere in Java 8, but I'm not familiar with the new collection features yet. Commented Jul 1, 2014 at 15:04

3 Answers 3

3

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)));
Sign up to request clarification or add additional context in comments.

3 Comments

The Streams solution still seems a bit verbose, but it's nice that it is at least possible now. I would have liked something along the lines of new HashMap<>().putAll(a).mergeAll(b, (v1,v2) -> v1+v2). Can't find anything corresponding to mergeAll in the docs, though. And of course Streams are more general than lots of specialized methods.
Thanks, very interesting although I was looking for a Java 6/7 solution.
II don't think you can improve your version much with Java 7.
1

I think what you are doing is just fine. I can think of one other way though, using a MultiMap. You can add all your elements to a multimap and then run a summation function over all the values for each key at the end.

Comments

1

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...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.