Reputation: 109
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 a 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?
Upvotes: 8
Views: 4509
Reputation: 393936
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.
Upvotes: 9
Reputation: 21239
The StreamEx library has the zipWith
method, which will zip two streams into a StreamEx EntryStream
. They can then be converted into a Map
using EntryStream.toMap
, using Integer.sum
as the merge function to add duplicate key values together.
Map<String, Integer> dictionary =
StreamEx.of(keys).zipWith(IntStreamEx.of(values)).toMap(Integer::sum);
Upvotes: 0
Reputation: 21239
The Google Guava library has the Streams.zip
method, which will zip two streams. The zipped stream can then be converted to a map using Collectors.toMap
, using Integer.sum
as the merge function to add duplicate key values together.
Map<String, Integer> dictionary =
Streams.zip(Arrays.stream(keys), Arrays.stream(values).boxed(), Map::entry)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum));
Upvotes: 0
Reputation: 44200
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.
Upvotes: 3