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 entries stream<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

Popular posts from this blog

sql - invalid in the select list because it is not contained in either an aggregate function -

Angularjs unit testing - ng-disabled not working when adding text to textarea -

How to start daemon on android by adb -