The Stream.flatMap()
operation transforms a stream of
a, b, c
into a stream that contains zero or more elements for each input el
This is what I came up with:
interface OptionalBinaryOperator extends BiFunction> {
static OptionalBinaryOperator of(BinaryOperator binaryOperator,
BiPredicate biPredicate) {
return (t1, t2) -> biPredicate.test(t1, t2)
? Optional.of(binaryOperator.apply(t1, t2))
: Optional.empty();
}
}
class StreamUtils {
public static Stream reducePartially(Stream stream,
OptionalBinaryOperator conditionalAccumulator) {
Stream.Builder builder = Stream.builder();
stream.reduce((t1, t2) -> conditionalAccumulator.apply(t1, t2).orElseGet(() -> {
builder.add(t1);
return t2;
})).ifPresent(builder::add);
return builder.build();
}
}
Unfortunately, I did not have the time to make it lazy, but it can be done by writing a custom Spliterator
delegating to stream.spliterator()
that would follow the logic above (instead of utilizing stream.reduce()
, which is a terminal operation).
PS. I just realized you wanted
conversion, and I wrote about
conversion. If you can first map from T
to U
, and then use the function above, then that's it (even if it's suboptimal).
If it's something more complex, the kind of condition for reducing/merging would need to be defined before proposing an API (e.g. Predicate
, BiPredicate
, BiPredicate
, or maybe even Predicate
).>