Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
117 views
in Technique[技术] by (71.8m points)

java - List<Map<String, Object>> to List<Map<String, Object>> group by key with nulls

I have a use case where I need to merge multiple rows from a query with the same key.

Input (List<Map<String, Object>>):

[
{"brand": "A", "sum of A": NULL, "sum of B": NULL, "sum of C": NULL, "sum of D": NULL},
{"brand": "B", "sum of A": 2700, "sum of B": 1500, "sum of C": NULL, "sum of D": NULL},
{"brand": "B", "sum of A": NULL, "sum of B": NULL, "sum of C": 1700, "sum of D": NULL},
{"brand": "C", "sum of A": 3000, "sum of B": NULL, "sum of C": NULL, "sum of D": NULL},
{"brand": "C", "sum of A": NULL, "sum of B": NULL, "sum of C": 6000, "sum of D": NULL},
{"brand": "D", "sum of A": 1000, "sum of B": 2000, "sum of C": 4000, "sum of D": 600}
]

Expected output (List<Map<String, Object>>):

[
{"brand": "A", "sum of A": NULL, "sum of B": NULL, "sum of C": NULL, "sum of D": NULL},
{"brand": "B", "sum of A": 2700, "sum of B": 1500, "sum of C": 1700, "sum of D": NULL},
{"brand": "C", "sum of A": 3000, "sum of B": NULL, "sum of C": 6000, "sum of D": NULL},
{"brand": "D", "sum of A": 1000, "sum of B": 2000, "sum of C": 4000, "sum of D": 600}
]

How can I achieve this with Java stream API? I can't use POJO because the data is always different, but I always know what is the name of the key (ex.: brand in that case). As you can see I always need the value instead of the NULL, but if there is no value, then we can use the NULL in the output.

And there is always only ONE value for the same key in the same column. So this is invalid input:

[
{"brand": "B", "sum of A": 2700, "sum of B": 1500, "sum of C": NULL, "sum of D": NULL},
{"brand": "B", "sum of A": 1400, "sum of B": NULL, "sum of C": 1700, "sum of D": NULL}
]

I don't need the exact return type for the output as long as it is easy to convert to JSON formatted String.

question from:https://stackoverflow.com/questions/65892191/listmapstring-object-to-listmapstring-object-group-by-key-with-nulls

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can do it using Collectors.toMap with mergeFunction, group the Map<String,Object> based on brand and then write the logic in merge function to merge the values of properties

Collection<Map<String,Object>> result =list.stream()
    .collect(Collectors.toMap(
            map -> map.get("brand"),
            Function.identity(),
            (existing, replacement) -> {
                //logic to merge m1 & m2
                replacement.forEach((key,val)-> {
                    existing.compute(key, (exKey, exVal) -> /*logic to sum*/)
                });
                return existing;
            }))
    .values();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...