[External] : Re: Stream Gatherers (JEP 473) feedback

Viktor Klang viktor.klang at oracle.com
Thu Sep 12 21:55:47 UTC 2024


Hi Anthony

Great questions! I had typed up a long response when my email client decided the email was too large, crashed, and deleted my draft, so I'll try to recreate what I wrote from memory.

>While I understand that most Gatherers will be reusable, and that it's a desirable characteristic, surely there will also be non-reusable Gatherers?

To me, this is governed by the following parts of the Gatherer specification<https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/util/stream/Gatherer.html>:

"Each invocation of initializer()<https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/util/stream/Gatherer.html#initializer()>, integrator()<https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/util/stream/Gatherer.html#integrator()>, combiner()<https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/util/stream/Gatherer.html#combiner()>, and finisher()<https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/util/stream/Gatherer.html#finisher()> must return a semantically identical result."

and

"Implementations of Gatherer must not capture, retain, or expose to other threads, the references to the state instance, or the downstream Gatherer.Downstream<https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/util/stream/Gatherer.Downstream.html>PREVIEW<https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/util/stream/Gatherer.Downstream.html#preview-java.util.stream.Gatherer.Downstream> for longer than the invocation duration of the method which they are passed to."

And I think the worst of all worlds would be a scenario where you, as a user, are given a Gatherer<X,Y,Z> and you have no idea whether you can re-use it or not.

For Stream, the assumption is that they are NOT reusable at all.
For Gatherer, I think the only reasonable assumption is that they are reusable.

>In particular, any Gatherer that is the result of a factory method with a `Stream<T>` parameter which supports infinite Streams, will be non-reusable, won't it?

Not necessarily, if the factory method consumes the Stream and creates a stable result which is reusable, then the resulting Gatherer is reusable.

>In a previous response you proposed using `Gatherer concat(Supplier<Stream<T>>)` instead, but then I'd just pass `() -> aStream`, wonder why the parameter isn't just a `Stream<T>`, and the Gatherer would still not be reusable.

There's a very important, to me, difference between the two. In the Stream-case, there exists 0 reusable usages. For the Supplier<Stream>-case the implementation does not restrict re-usability, but rather it is up to the caller to actively opt-out of reusability (which could of course also be declared to be undefined behavior of the implementor of said Gatherer). Local non-reusability decided by the caller > Global non-reusability decided by the callee.

>As another example, take Gunnar Morling's zip Gatherers:
I don't see how Gatherers like this could be made reusable, or why that would even be desirable.

Having been R&D-ing in the Stream-space more than a decade, I'm convinced that there's no universally safe way to implement `zip` for push-style stream designs. I'm happy to be proven wrong though, as that would open up some interesting possibilities for things like Stream::iterator() and Stream:spliterator().

>My use case was about a pipeline where the concatenation comes somewhere in the middle of the pipeline.

My apologies, I misunderstood. To me, the operation you describe is called `inject`.
Given a stable (reusable) source of elements you can definitely implement Gatherers which do before, during, or after-injections of elements to a stream.

Thanks again for the great questions and conversation, it's valuable!

Cheers,
√


Viktor Klang
Software Architect, Java Platform Group
Oracle

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20240912/56e54652/attachment.htm>


More information about the core-libs-dev mailing list