Можем ли мы использовать java Stream для рефакторинга? - PullRequest
0 голосов
/ 06 июня 2018

Возможно ли рефакторинг в следующем цикле for с использованием Stream s в 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 ]

0 голосов
/ 06 июня 2018

Попробуйте это:

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())));
0 голосов
/ 06 июня 2018

Еще одна опция, с 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);   

Трех аргумент collect позволяет указать точную реализацию возвращаемой карты.Это может или не может быть необходимым для контроля над этим - в зависимости от того, для чего вам нужна карта.

0 голосов
/ 06 июня 2018

Вот один из способов, используя 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;}));

Который, как прокомментировал Аомин, может быть упрощено до:

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;}));
...