Can we use java Stream to refactor this?

convert java code to java 8 online
intellij convert java 8 to java 7
convert code to java 8 online
convert java 7 code to java 8 in eclipse
convert java 7 code to java 8 online
java 8 to java 7 converter online
intellij java 8 suggestions
why use java streams

Is it possible to refactor the following for loop using Streams in Java 8?

Moving the state from the inside to outside while collecting the list for different sources?

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

Recently I tried several use cases but it just seems ugly to me.

I tried to use stream().map() to achieve that, but I failed. Can anyone please help?

Try this:

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())));

Refactoring for Java 8 Streams, As a Java Developer who is very familiar with the Java Collections API, I was excited to learn about the Lambdas and Streams APIs that are a  Refactoring for Java 8 Streams. As a Java Developer who is very familiar with the Java Collections API, I was excited to learn about the Lambdas and Streams APIs that are a part of the Java 8 release. An increase in performance when processing collections, and a lean coding syntax were both promised, and it appears the Java 8 team has delivered.

Here's one way, using collect instead of forEach to generate the Map, and using flatMap to eliminate the for loop:

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

Which, as Aominè commented, can be simplified to:

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

How to refactor function chains for Java 8 Streams, Apart from the obvious solution of an utility method (already mentioned in my comment), I think the most straightforward idea to keep it OO is to  Optimize Java 8 Streams Refactoring. Introduction. The Java 8 Stream API sets forth a promising new programming model that incorporates functional-like, MapReduce-style features into a mainstream programming language. However, using streams efficiently may involve subtle considerations.

One more option, with 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);   

The three-argument collect allows to specify exact implementation of the map it returns. It may or may not be necessary to have control over that - depending on what you need the map for.

IntelliJ IDEA Inspection Settings for Refactoring to Java 8, I've been giving a talk this year showcasing how to use IntelliJ IDEA inspections to help you refactor existing code to Java 8. The initial version  The addition of the Stream is one of the major new functionality in Java 8. This in-depth tutorial is an introduction to the many functionalities supported by streams, with a focus on simple, practical examples. To understand this material, you need to have a basic, working knowledge of Java 8 (lambda expressions, Optional, method references).

How to Reuse Java Streams, In order to understand all details of this article you must be familiarized with streams terminology. Streams Use Case. Stream operations are very  The first refactoring we will use is extract constant. This will take a hard coded value and extract it as a constant. I’ll do this with the number 3. I’ll highlight the value.

Java Stream reuse - traverse stream multiple times?, Java streams, once consumed, can not be reused by default. which require to traverse the stream multiple times – isn't efficient code and need to be refactored. In that case, we can always use stream() method or just create a fresh stream. However by using an automated tool, the refactorings can be completed quickly so that other developers are not held up waiting to make there changes when the refactoring is completed, or worse making their changes on the old code at the same time as the refactoring operation.

5 ways to Convert Java 8 Stream to List - Example , Here you will find methods like toList(), which can be used to convert Java 8 Stream to there is something you can use to convert a Java 8 Stream to List. Refactoring to Java 8 Streams and Lambdas Self- Study Workshop Although there is always more to refactor in a code base, start small and make progress. Completing a small refactoring earns us a level of confidence and satisfaction. With a goal in mind, we can now provide the technical requirement for refactoring: Quick and automated tests.

Comments
  • dumpDoList.forEach(dumpDo -> { ... }) would work, but seriously don't use streams for the sake of using streams. They won't make your code more readable in every context and probably not in this context.
  • i think flatMap should be in your code!
  • @Synth Yes, you are right. But I think at least sometimes I should have a try to refactor so when I really need it, I can smoothly do it.
  • @YCF_L Just tested and you are right. Thank you ~
  • for(ThreadDumpDo dumpDo : dumpDoList) getStateGroup(dumpDo) .forEach((k,v) -> stateDumpListMap.computeIfAbsent(k, x -> new ArrayList<>()) .add(v));
  • This is really nice and generic code, I think for OP it suits best in case the toMap needs to be highly customizable.
  • The value mapper can be simplified to e -> new ArrayList<>(Collections.singletonList(e.getValue()))
  • @Aominè thanks! I could have used new ArrayList<>(Arrays.asList()) too.