V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nthin0
V2EX  ›  Java

求助,关于 java8 Collectors 的 groupingBy 和 mapping

  •  
  •   nthin0 · 2018-10-17 01:27:37 +08:00 · 4256 次点击
    这是一个创建于 2267 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题描述

    • 小弟尝试将一段如下 json 读到一个 Map<String, List<string>>中,map 的 key 为 condName,map 的 value 为 condValue</string>
    • 现在用 stream 结合 Collectors 的 groupingBy 和 toList 方法,将 List<condition>转成了 Map<String, List<condition>></condition></condition>
    • 然后尝试通过 mapping 方法将 List<condition>映射为 List<string>时发现无从下手。。。几次尝试后得到了一个 Map<String, List<List<string>>>,多了一层 List</string></string></condition>
    • 想去掉这一层 List,如果再遍历一遍又感觉不太优雅
    • 求助各位有什么思路吗,最好是通过 mapping 一次得到想要的结果
    • 不胜感激!

    相关代码

    {
        "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();
    }
    
    • map1:
    {name3=[Condition(condName=name3, condValue=[val31, val32, val33])], name2=[Condition(condName=name2, condValue=[val21])], name1=[Condition(condName=name1, condValue=[val11, val12])]}
    
    • map2:
    {name3=[[val31, val32, val33]], name2=[[val21]], name1=[[val11, val12]]}
    
    6 条回复    2018-10-17 21:46:46 +08:00
    Raymon111111
        1
    Raymon111111  
       2018-10-17 02:00:09 +08:00
    感觉你需要的是 Collectors.toCollection 这个
    SoloCompany
        2
    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
        3
    nl101531  
       2018-10-17 07:55:16 +08:00   ❤️ 1
    直接 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
        4
    nthin0  
    OP
       2018-10-17 09:49:41 +08:00 via iPhone
    @nl101531 搞定了,非常感谢!😃😃
    519718366
        5
    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
        6
    nthin0  
    OP
       2018-10-17 21:46:46 +08:00 via iPhone
    @519718366 谢谢解答,感觉对 reducing 有了新的理解,非常感谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1000 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 20:16 · PVG 04:16 · LAX 12:16 · JFK 15:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.