Tip of the day #21

Use flatMap to avoid nested Collections.

Remember tip #18 groupingBy. You have a Map<String, List> mapAccount after the groupingBy.

Imagine that you need a big ONE list of accounts. If you try mapAccount.values() you will have List<List> and this is not the desirable result.

For this, you can use flatMap:

    System.out.println(accountMap.values()); // List<List<Account>> 
    System.out.println(accountMap.values().stream().flatMap(Collection::parallelStream).toList()); // List<Account>

What is it?

The flatMap method definition is hard to read and understand:

Returns a stream consisting of the results of replacing each element of this stream

with the contents of a mapped stream produced by applying the provided mapping function to each element.

    flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

You will need to pass a function, that will be applied in your stream, and it will return something for you.

Let’s see our method again:

    accountMap.values().stream().flatMap(Collection::parallelStream).toList()

Now we have a Collection<List> and flatMap is an intermediate operation - this is why to get the final List we use

the toList() to consume the final stream and create a final List.

From the doc we can have a better definition:

The flatMap() operation has the effect of applying a one-to-many transformation to the elements of the stream,

and then flattening the resulting elements into a new stream.

So to understand, when I call values().stream() I create a Stream<List>, and when I call flatMap(Collection::parallelStream), each List will become a Stream and "appended" in sequential order. So I can have different order in each List - because of the parallel, but not between the lists.

Hope this helps you, if not, try to see the How to section.

How to

Take a look in repo-tip-20 to see a real example of today’s tip.