代码之家  ›  专栏  ›  技术社区  ›  Hearen

我们可以用Java流重构这个吗?

  •  4
  • Hearen  · 技术社区  · 7 年前

    有可能 重构 以下 for 循环使用 Stream 在Java 8中?

    在收集不同来源的列表时将状态从内到外移动?

    Map<StateEnum, List<List<ThreadDo>>> stateDumpListMap = new HashMap<>();
    for (ThreadDumpDo dumpDo : dumpDoList) {
        Map<StateEnum, List<ThreadDo>> stateDoListMap = getStateGroup(dumpDo);
        stateDoListMap.entrySet().stream().forEach(entry -> {
           stateDumpListMap.putIfAbsent(entry.getKey(), new ArrayList<>());
           stateDumpListMap.get(entry.getKey()).add(entry.getValue());
         });
    }
    

    最近我尝试了几个用例,但对我来说这看起来很难看。

    我试着用 stream().map() 但我失败了。有人能帮忙吗?

    3 回复  |  直到 7 年前
        1
  •  1
  •   Lii bob    7 年前

    试试这个:

    Map<StateEnum, List<List<ThreadDo>>> stateDumpListMap = dumpDoList.stream()
        .flatMap(dumpDo -> getStateGroup(dumpDo).entrySet().stream())
        .collect(Collectors.groupingBy(
            entry -> entry.getKey(),
            Collectors.mapping(entry -> entry.getValue(), Collectors.toList())));
    
        2
  •  3
  •   Eran    7 年前

    有一种方法,使用 collect 而不是 forEach 生成 Map 并使用 flatMap 消除 for 循环:

    Map<StateEnum, List<List<ThreadDo>>> stateDumpListMap =
        dumpDoList.stream ()
                  .flatMap (d->getStateGroup(d).entrySet().stream ())
                  .collect(Collectors.toMap (Map.Entry::getKey,
                                             e -> {
                                                List<List<ThreadDo>> l = new ArrayList<>(); 
                                                l.add (e.getValue());
                                                return l;
                                             },
                                             (v1,v2)->{v1.addAll(v2);return v1;}));
    

    正如aomin所评论的,可以简化为:

    Map<StateEnum, List<List<ThreadDo>>> stateDumpListMap =
        dumpDoList.stream ()
                  .flatMap (d->getStateGroup(d).entrySet().stream ())
                  .collect(Collectors.toMap (Map.Entry::getKey,
                                             e -> new ArrayList<>(Collections.singletonList(e.getValue())),
                                             (v1,v2)->{v1.addAll(v2);return v1;}));
    
        3
  •  1
  •   Hearen    7 年前

    还有一个选择 collect :

    Map<StateEnum, List<List<ThreadDo>>> stateDumpListMap = dumpDoList.stream()
        .map(this::getStateGroup)   // dumpDo mapped to stateDoListMap  ( Map<StateEnum, List<ThreadDo>> )
        .map(Map::entrySet)         // stream of sets of entries of stateDoListMap (Entry<StateEnum, List<ThreadDo>>)
        .flatMap(Set::stream)       // stream of entries of all stateDoListMaps 
        .collect(HashMap::new,      // collect to a new HashMap, types infered from the variable declaration
                (map, stateDoListMapEntry) -> map.computeIfAbsent(stateDoListMapEntry.getKey(), key -> new ArrayList<>()).add(stateDoListMapEntry.getValue()), // for each entry incoming from the stream, compute it if does not exist in the target map yet (create the top level list), then add List<ThreadDo> to it.
                Map::putAll);   
    

    三个论点 收集 允许指定它返回的映射的精确实现。可能需要也可能不需要控制它,这取决于你需要地图做什么。