Perform flatMap operation with Collectors

The Apprentice :

I would like to understand a way to perform a flatMap while using Collectors. Here is an example.

Scenario:

I have the following interfaces:

interface Ic {
    //empty
}

interface Ib {
    Stream<Ic> getCs();
}

interface Ia {
    String getName();
    Stream<Ib> getBs();
}

And I'm trying to implement the following method:

Map<String, Long> total_of_C_per_A (Stream<Ia> streamOfA) {
   return streamOfA.collect(groupBy(Ia::getName, ???));
}

The classification function is pretty straitforward, my problem is with the downstream collector. I need to count the number of "C" associated with "A".

What I tried to to:

If I wanted to simply return the count, without creating a map, I would do:

streamOfA
  .flatMap(Ia::getBs)
  .flatMap(Ib::getCs)
  .count();

But the Collectors class only allows me to do mapping operations. What else can I try to do?

Thanks.

Holger :

This answer points you already into the right direction, but there is no need to nest multiple mapping collectors, as you can just write these functions into a single lambda expression. Considering that the summingLong collector expects a function which evaluates to long, you can simply pass that function to the collector without any mapping collector at all:

Map<String, Long> total_of_C_per_A (Stream<Ia> streamOfA) {
    return streamOfA.collect(groupingBy(
            Ia::getName,
            summingLong(ia -> ia.getBs().flatMap(Ib::getCs).count())));
}

This also has the advantage that the long values are not boxed to Long instances.

There’s also an alternative to flatMap:

Map<String, Long> total_of_C_per_A (Stream<Ia> streamOfA) {
    return streamOfA.collect(groupingBy(
            Ia::getName,
            summingLong(ia -> ia.getBs().mapToLong(ib -> ib.getCs().count()).sum())));
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=472044&siteId=1