lambda - Merge list of maps using Java 8 Stream API -
i'm trying learn java 8 stream , when try convert function java8 practice. meet problem.
i'm curious how can convert follow code java stream format.
/* * input example: * [ { "k1": { "kk1": 1, "kk2": 2}, "k2": {"kk1": 3, "kk2": 4} } { "k1": { "kk1": 10, "kk2": 20}, "k2": {"kk1": 30, "kk2": 40} } ] * output: * { "k1": { "kk1": 11, "kk2": 22}, "k2": {"kk1": 33, "kk2": 44} } * * */ private static map<string, map<string, long>> mergemapsvalue(list<map<string, map<string, long>>> valuelist) { set<string> keys_1 = valuelist.get(0).keyset(); set<string> keys_2 = valuelist.get(0).entryset().iterator().next().getvalue().keyset(); map<string, map<string, long>> result = new hashmap<>(); (string k1: keys_1) { result.put(k1, new hashmap<>()); (string k2: keys_2) { long total = 0; (map<string, map<string, long>> mmap: valuelist) { map<string, long> m = mmap.get(k1); if (m != null && m.get(k2) != null) { total += m.get(k2); } } result.get(k1).put(k2, total); } } return result; }
the trick here collect correctly inner maps. workflow be:
- flat map list of map
list<map<string, map<string, long>>>
stream of map entriesstream<map.entry<string, map<string, long>>>
. - group key of each of entry, , values mapped same key, merge 2 maps together.
collecting maps merging them ideally warrant flatmapping
collector, unfortunately doesn't exist in java 8, although it exist in java 9 (see jdk-8071600). java 8, possible use 1 provided streamex library (and use morecollectors.flatmapping
in following code).
private static map<string, map<string, long>> mergemapsvalue(list<map<string, map<string, long>>> valuelist) { return valuelist.stream() .flatmap(e -> e.entryset().stream()) .collect(collectors.groupingby( map.entry::getkey, collectors.flatmapping( e -> e.getvalue().entryset().stream(), collectors.<map.entry<string,long>,string,long>tomap(map.entry::getkey, map.entry::getvalue, long::sum) ) )); }
without using convenient collector, can still build our own equivalent semantics:
private static map<string, map<string, long>> mergemapsvalue2(list<map<string, map<string, long>>> valuelist) { return valuelist.stream() .flatmap(e -> e.entryset().stream()) .collect(collectors.groupingby( map.entry::getkey, collector.of( hashmap::new, (r, t) -> t.getvalue().foreach((k, v) -> r.merge(k, v, long::sum)), (r1, r2) -> { r2.foreach((k, v) -> r1.merge(k, v, long::sum)); return r1; } ) )); }
Comments
Post a Comment