lambda - Java 8 streams reduce and combine List items to Map -
i need create map keys of name1/2 summing values value1/2.
what cleanest way rewrite using java 8 streams?
class item { private string name1; private integer value1; private string name2; private integer value2; public item(final string name1, final integer value1, final string name2, final integer value2) { this.name1 = name1; this.value1 = value1; this.name2 = name2; this.value2 = value2; } //getters , setters }
list<item> list = lists.newarraylist( new item("aaa", 1, "bbb", 2), new item("bbb", 5, "ccc", 3), new item("aaa", 8, "bbb", 7), new item("bbb", 2, "aaa", 5)); map<string, integer> map = maps.newhashmap(); (item item : list) { map.merge(item.name1, item.value1, integer::sum); map.merge(item.name2, item.value2, integer::sum); } system.out.println(map);//{aaa=14, ccc=3, bbb=16}
a possible solution flat map each item stream made 2 entries: each entry composed of name , corresponding value. then, collected map summing values of values having same key. since there no built-in pair hold both values, can use abstractmap.simpleentry
.
map<string, integer> map = list.stream() .flatmap(i -> stream.of(new abstractmap.simpleentry<>(i.name1, i.value1), new abstractmap.simpleentry<>(i.name2, i.value2))) .collect(collectors.tomap(map.entry::getkey, map.entry::getvalue, integer::sum));
alternatively, might simpler use custom collect
call. accumulator merges each key, have in for
loop body. tricky part combiner, in case merges 2 maps iterating on entries of second map , merging them first one.
map<string, integer> map = list.stream() .collect( hashmap::new, (m, i) -> { m.merge(i.name1, i.value1, integer::sum); m.merge(i.name2, i.value2, integer::sum); }, (m1, m2) -> m2.foreach((k, v) -> m1.merge(k, v, integer::sum)) );
Comments
Post a Comment