Thanks Viktor,

The flexibility of streams and gatherers is always impressive. Thanks for
the example.

The example makes sense, I actually did something quite similar myself,
except using plain mapMulti from the base stream api itself.

It is a shame that the core functionality is not quite there, but the
workarounds are good enough for my purposes, for now.

Ty for the help!


On Tue, Jun 2, 2026 at 7:23 AM Viktor Klang <[email protected]> wrote:

> Hi David,
>
> This is a really complex topic, and there are interactions between
> things like Errors/RuntimeExceptions and Throwables, together with
> sequential evaluation, parallel evaluation, partial evaluation etc.
>
> That being said, Gatherers are extremely versatile, and you could
> experiment with encodings that would allow you to add the kind of
> information you need.
>
> The following is just an example I threw together to illustrate what I
> mean:
>
> jshell> public static <T, R> Gatherer<T, ?, R> wrap(Function<? super T,
> ? extends Stream<? extends R>> f, BiFunction<? super T, ? super
> RuntimeException, ? extends RuntimeException> wrapper) {
>     ...>     return Gatherer.<T, Void, R>of( // flatMap-semantics
>     ...>         Gatherer.defaultInitializer(),
>     ...>         (_, element, downstream) -> {
>     ...>             try(Stream<? extends R> s = f.apply(element)) {
>     ...>                 return s != null ?
> s.sequential().allMatch(downstream::push) : true; // Not ideal
> performance-wise, yet semantically works
>     ...>             } catch (RuntimeException re) {
>     ...>                 throw wrapper.apply(element, re);
>     ...>             }
>     ...>         },
>     ...>         (Void x, Void y) -> x, // "custom" combiner so this
> operation can be parallelized
>     ...>         Gatherer.defaultFinisher()
>     ...>     );
>     ...> }
> |  created method wrap(Function<? super T, ? extends Stream<? extends
> R>>, BiFunction<? super T, ? super RuntimeException, ? extends
> RuntimeException>)
>
> jshell> Stream.of(1,2, 0, 3).gather(wrap(i -> Stream.of(i).map(x -> 10 /
> x), (i, e) -> new IllegalStateException("Error when processing: " + i,
> e))).toList();
> |  Exception java.lang.IllegalStateException: Error when processing: 0
> |        ... // trace here
> |  Caused by: java.lang.ArithmeticException: / by zero
> |        ... // trace here
>
>
> On 2026-06-02 02:17, David Alayachew wrote:
> > Whoops, let me improve that method signature.
> >
> > public <X1 extends Throwable, X2 extends Throwable> Stream<T>
> > wrapException(Class<X1> excClass, Function<X1, X2> excTransformer)
>
> --
> Cheers,
> √
>
>
> Viktor Klang
> Software Architect, Java Platform Group
> Oracle
>
>

Reply via email to