views:

117

answers:

6

Hi

Say I have two hashmaps:

  1. {dog=1, cat=1, sport=3, golf=4}
  2. {dog=5, person=1, animal=4}

I want to merge them retaining the values, so that the values add together in the output

Output:

{dog=6, person=1, animal=4, cat=1, sport=3, golf=4}

Notice how "dog" has a value of 6 (5+1)

Using Hashmap.putAll(), the value of dog becomes 5, any ideas how I can merge these retaining the values?

Many thanks, Philip

+1  A: 
HashMap merged = new HashMap<String, Integer>();

for (String x : map1.getKeySet()) {
   Integer y = map2.get(x);
   if (y == null) {
      merged.put(x, map1.get(x));
   } else {
      merged.put(x, map1.get(x)+y);
   }
}

for (String x : map2.getKeySet()) {
   if (merged.get(x) == null) {
      merged.put(x, map2.get(x));
   }
} 

Just threw that together - not saying it's the best way.

Gandalf
A: 

Take the larger one, and loop along the smaller one, adding the nonexisting entries, and adjusting the value for existing ones.

Frank
A: 

If you put a duplicate key, value into a map in java it will replace whatever value was previously there.

You could check to see if the value exists so

Map outputMap = new HashMap<String, Integer>()
for(Map.Entry<String, Integer> entry : map1.entrySet()){
   if(map2.contains(entry.getKey()){
     outputMap.put(entry.getKey(), entry.getValue() + map2.get(entry.getKey());
     map2.remove(entry.getKey());  
   }
   else
     outputMap.put(entry.getKey(), entry.getValue()
}
outputMap.addAll(map2); 
dave
+2  A: 

Google's open source Guava Library has a class called Multiset which entirely abstracts out the need for a Map<T,Integer> for counting instances of T.

You'll find that using Multiset<String> instead of using a Map<String,Integer> will result in less code which is less error prone to do the same thing.

Using Multiset, to merge the two you would just say:

multiset1.addAll(multiset2);
Michael D
+1, the `Multiset` is perfect for this question!
Adam Paynter
While a good answer, adding a 3rd party library to do a simple merge seems a bit overkill - not a lot about this code that is "error prone"
Gandalf
@Gandalf: I agree with all points in your comment. For the record, I like the `Multiset` approach not because it's less "error prone" but because it seems like the best data structure for the job. :)
Adam Paynter
A: 

This would be the simplest non destructive way to do it although it might not be as efficient as two loops since both keysets are inserted into a 3rd.

HashSet<String> allKeys = new HashSet<String>();
HashMap<String, Integer> resultMap = new HashMap<String, Integer>();
allKeys.addAll(map1.keySet());
allKeys.addAll(map2.keySet());
for (String k : allKeys) {
  int i1 = map1.containsKey(k) ? map1.get(k) : 0;
  int i2 = map2.containsKey(k) ? map2.get(k) : 0;
  resultMap.put(k, i1 + i2);
}
locka
A: 

To shorten the loops you can.

Map<String, Integer> merged = new HashMap<String, Integer>(map1); 
for (Map.Entry<String, Integer> entry : map2.entrySet()) {
   Integer y = merged.get(entry.getKey()); 
   merged.put(entry.getKey(), entry.getValue() + (y == null ? 0 : y));
} 
Peter Lawrey