Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge two arrays into a map using Java streams?

Lets suppose we were given the following two arrays

String[] keys   = new String[] {"a", "b", "c", "aa", "d", "b"}
int[]    values = new int[]    { 1 ,  2 ,  3 ,  4  ,  5 ,  6 }

And by merging these 2 arrays into HashTable we get the following

// pseudo-code
Map<String, Integer> dictionary = new HashTable<>(
  ("a"  => 1)
  ("b"  => 8) // because "b" appeared in index 1 and 5
  ("c"  => 3)
  ("aa" => 4)
  ("d"  => 5)
);

How can we do this using java Lambda style?

So far I have the following:

// this loops through the range given (used for index start and end)
// and sums the values of duplicated keys
tree.listMap = IntStream.range(range[0], range[1]).boxed().collect(
  Collectors.toMap(i - > dictionary[i], i - > i + 1, Integer::sum, TreeMap::new)
);

However, I'd like to take 2 arrays, merge them by key and value, where value is the sum of all values for duplicated keys. How can we do this?

like image 968
Jamie Avatar asked Oct 26 '17 07:10

Jamie


2 Answers

There you go:

Map<String,Integer> themap = 
       IntStream.range (0, keys.length).boxed()
                .collect (Collectors.toMap(i->keys[i],
                                           i->values[i],
                                           Integer::sum,
                                           TreeMap::new));

Output:

{a=1, aa=4, b=8, c=3, d=5}

This is quite similar to the snippet you posted, though, for some reason, the snippet you posted contains no reference to the keys and values arrays.

like image 136
Eran Avatar answered Oct 17 '22 08:10

Eran


I don't like using streams when referring to indexes, but you can use groupingBy and summingInt to accomplish this:

Map<String, Integer> result = IntStream.range(0, keys.length)
   .boxed()
   .collect(
       Collectors.groupingBy(
           i -> keys[i],
           Collectors.summingInt(i -> values[i])
       )
   );

Note that this works on the assumption that keys and values are both of equal length, so you may want to do some additional validation.

like image 38
Michael Avatar answered Oct 17 '22 08:10

Michael