I got in touch with a new feature since java-9 called Collectors.flatMapping that takes place as a downstream of grouping or partitioning. Such as (example taken from here):
I would just backport flatMapping
. It only requires 2 methods and 1 class, with no other dependencies.
Also, when it comes time to upgrade to Java 9, you can just deprecate your version and replace any usages of it with the proper version.
The following code is taken from the JDK. I didn't write it. I have tested it with your example and it returns the same result.
class Nikollectors
{
public static Collector flatMapping(Function super T, ? extends Stream extends U>> mapper, Collector super U, A, R> downstream) {
BiConsumer downstreamAccumulator = downstream.accumulator();
return new CollectorImpl<>(downstream.supplier(),
(r, t) -> {
try (Stream extends U> result = mapper.apply(t)) {
if (result != null)
result.sequential().forEach(u -> downstreamAccumulator.accept(r, u));
}
},
downstream.combiner(), downstream.finisher(),
downstream.characteristics());
}
private static class CollectorImpl implements Collector
{
private final Supplier supplier;
private final BiConsumer accumulator;
private final BinaryOperator combiner;
private final Function finisher;
private final Set characteristics;
CollectorImpl(Supplier supplier,
BiConsumer accumulator,
BinaryOperator combiner,
Function finisher,
Set characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
}
CollectorImpl(Supplier supplier,
BiConsumer accumulator,
BinaryOperator combiner,
Set characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
}
@Override
public BiConsumer accumulator() {
return accumulator;
}
@Override
public Supplier supplier() {
return supplier;
}
@Override
public BinaryOperator combiner() {
return combiner;
}
@Override
public Function finisher() {
return finisher;
}
@Override
public Set characteristics() {
return characteristics;
}
}
private static Function castingIdentity() {
return i -> (R) i;
}
}
Sample usage:
Map> map =list.stream()
.collect(Collectors.groupingBy(
Collection::size,
Nikollectors.flatMapping( // <<<
l -> l.stream().filter(i -> i % 2 == 0),
Collectors.toList()
)
)
);