求助,关于 java8 Collectors 的 groupingBy 和 mapping

2018-10-17 01:27:37 +08:00
 nthin0

问题描述

相关代码

{
    "condition": [
        {
            "condName": "name1",
            "condValue": [
                "val11",
                "val12"
            ]
        },
        {
            "condName": "name2",
            "condValue": [
                "val21"
            ]
        },
        {
            "condName": "name3",
            "condValue": [
                "val31",
                "val32",
                "val33"
            ]
        }
    ],
    "total": 3
}
@Data
public class Request {
    private List<Condition> condition;
    private Long total;
}
@Data
public class Condition {
    private String condName;
    private List<String> condValue;
}

转换方法(读取 json 和转成 Request 对象的代码省略。。。):

String json = getContent();
try {
    List<Condition> conditions = deseriliaze(json).getCondition();
    Map<String, List<Condition>> map1 = conditions.stream().collect(Collectors.groupingBy(Condition::getCondName));
    Map<String, List<List<String>>> map2 = conditions.stream().collect(Collectors.groupingBy(Condition::getCondName, Collectors.mapping(Condition::getCondValue, Collectors.toList())));
} catch (Exception e) {
    e.printStackTrace();
}
{name3=[Condition(condName=name3, condValue=[val31, val32, val33])], name2=[Condition(condName=name2, condValue=[val21])], name1=[Condition(condName=name1, condValue=[val11, val12])]}
{name3=[[val31, val32, val33]], name2=[[val21]], name1=[[val11, val12]]}
4239 次点击
所在节点    Java
6 条回复
Raymon111111
2018-10-17 02:00:09 +08:00
感觉你需要的是 Collectors.toCollection 这个
SoloCompany
2018-10-17 03:24:26 +08:00
groupingBy 需要指定 downstream Collector 而不是默认的 toList
downstream Collector 需要使用 reducer (reducing)
reducer 把 Condition 先 map 成 List<String> 然后再通过 addAll 拼接(reduce)成新的 List<String>
nl101531
2018-10-17 07:55:16 +08:00
直接 toMap 就可以变成 String, List<String>了。

```java
Map<String, List<String>> listMap = conditions.stream()
.collect(Collectors.toMap(
Condition::getCondName,
Condition::getCondValue,
(v1, v2) -> {v1.addAll(v2);return v1;}));
```
nthin0
2018-10-17 09:49:41 +08:00
@nl101531 搞定了,非常感谢!😃😃
519718366
2018-10-17 17:49:56 +08:00
nl101531 这种写法我个人觉得不太灵活,因为 toMap 的第三个参数 mergeFunction 只能返回 List 类型,如果楼主有对最后的这个集合采用 set 进行去重,那就不太方便了,我个人推荐下面这种写法 https://stackoverflow.com/questions/32252628/how-to-use-java-8-stream-and-lambda-to-flatmap-a-groupingby-result/32253225

核心就是进行 groupingby 操作时,downloadstream 进行转换操作
conditions.stream().collect(Collectors.groupingBy(Condition::getCondName, Collectors.mapping(Condition::getCondValue, Collector.of(ArrayList::new, List::addAll, (x, y) -> {x.addAll(y);return x;})));

核心就是 Collector.of(...)。如果你提供 ArrayList,那最后就是 List<String>,如果你提供 HashSet 那最后就是 Set<String>
nthin0
2018-10-17 21:46:46 +08:00
@519718366 谢谢解答,感觉对 reducing 有了新的理解,非常感谢!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/498290

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX