I would like to understand a way to perform a flatMap
while using Collector
s. 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.
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())));
}