Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way to flatMap Set of Sets inside groupingBy

So I have a piece of code where I'm iterating over a list of data. Each one is a ReportData that contains a case with a Long caseId and one Ruling. Each Ruling has one or more Payment. I want to have a Map with the caseId as keys and sets of payments as values (i.e. a Map<Long, Set<Payments>>).

Cases are not unique across rows, but cases are.

In other words, I can have several rows with the same case, but they will have unique rulings.

The following code gets me a Map<Long, Set<Set<Payments>>> which is almost what I want, but I've been struggling to find the correct way to flatMap the final set in the given context. I've been doing workarounds to make the logic work correctly using this map as is, but I'd very much like to fix the algorithm to correctly combine the set of payments into one single set instead of creating a set of sets.

I've searched around and couldn't find a problem with the same kind of iteration, although flatMapping with Java streams seems like a somewhat popular topic.

rowData.stream()
        .collect(Collectors.groupingBy(
            r -> r.case.getCaseId(),
            Collectors.mapping(
                r -> r.getRuling(),
                Collectors.mapping(ruling->
                    ruling.getPayments(),
                    Collectors.toSet()
                )
            )));
like image 830
Lars Holdaas Avatar asked Sep 28 '18 08:09

Lars Holdaas


People also ask

What does the map () flatMap () function do?

Both of the functions map() and flatMap are used for transformation and mapping operations. map() function produces one output for one input value, whereas flatMap() function produces an arbitrary no of values as output (ie zero or more than zero) for each input value. Where R is the element type of the new stream.

Does flatMap preserve order?

Does flatmap() method preserve the order of the streams? Yes, It does and map() also.

What is flattening in flatMap?

In Java 8 Streams, the flatMap() method applies operation as a mapper function and provides a stream of element values. It means that in each iteration of each element the map() method creates a separate new stream. By using the flattening mechanism, it merges all streams into a single resultant stream.

How do you use flatMap in stream?

Stream flatMap() in Java with examples. Stream flatMap(Function mapper) 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.


1 Answers

Another JDK8 solution:

Map<Long, Set<Payment>> resultSet = 
         rowData.stream()
                .collect(Collectors.toMap(p -> p.Case.getCaseId(),
                        p -> new HashSet<>(p.getRuling().getPayments()),
                        (l, r) -> { l.addAll(r);return l;}));

or as of JDK9 you can use the flatMapping collector:

rowData.stream()
       .collect(Collectors.groupingBy(r -> r.Case.getCaseId(), 
              Collectors.flatMapping(e -> e.getRuling().getPayments().stream(), 
                        Collectors.toSet())));
like image 131
Ousmane D. Avatar answered Sep 20 '22 00:09

Ousmane D.