Hi Cay!

Thanks for the questions, see my responses below:

>1. "Gatherers whose integrator is an instance of Gatherer.Integrator.Greedy 
>can be >assumed not to short-circuit, *and the return value of invoking 
>>Gatherer.Integrator.integrate(Object, Object, Downstream) does not need to be 
>>inspected*."

>The way it is worded, I get the impression that a greedy integrator could 
>simply >return false (or to save a letter, true), because, not inspected. But 
>I am confused. It >was my impression that any integrator, greedy or not, 
>should return false if >downstream.push returns false. Why would the 
>implementation not want to >know? (The current implementation does inspect the 
>return value.)

No, it doesn't say that it won't be inspected, it says that it doesn't need to. 
So if a user returns false from a greedy integrator's integrate-method, they 
can't be surprised if that signal isn't acted upon.

The "evaluator" which operates on the Gatherer instance then has more freedom 
as to how it is implemented when it sees Greedy Integrators.

>2. "Gatherers whose finisher is defaultFinisher() are considered to not have 
>an >end-of-stream hook *and invoking their finisher is optional.*"

>I don't get the significance of the "and" part. Why would anyone care if 
>>defaultFinisher is invoked? It's a no-op.

For developers: If the user has to implement the Gatherer interface and 
overrides/implements the finisher()-method, it does not need to synthesize a 
no-op (bi-)consumer, which will end up being invoked needlessly, but instead 
they can return the `defaultFinisher()` which indeed is how the default 
implementation of Gatherer::finisher() is implemented: 
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/stream/Gatherer.java#L250

For developers who venture into overriding andThen(), knowing which finishers 
are no-ops, and thus do not need to be composed, reduces the cost of invoking 
them.

For implementors of things which evaluate Gatherers: they can now avoid the 
overhead of invoking no-op finishers (which tend to be fairly common).

>3. What is the use case for

>static <T,R> Gatherer<T,Void,R>
>of(Gatherer.Integrator<Void,T,R> integrator, BiConsumer<Void, 
>>Gatherer.Downstream<? super R>> finisher)

>If there is no state, what can the finisher do?

Inject known data at the end of a stream, for instance:

jshell> Gatherer<String, Void, String> s = Gatherer.of((_, s, d) -> d.push(s), 
(_, d) -> d.push("EOF"))
s ==> GathererImpl[initializer=DEFAULT, integrator=$Lam ... 
0000007e000cf838@5f3a4b84]

jshell> Stream.of("foo", "bar", "baz").gather(s).toList()
$2 ==> [foo, bar, baz, EOF]


Cheers,
√


Viktor Klang
Software Architect, Java Platform Group
Oracle

________________________________
From: core-libs-dev <core-libs-dev-r...@openjdk.org> on behalf of Cay Horstmann 
<cay.horstm...@gmail.com>
Sent: Thursday, 19 June 2025 12:25
To: core-libs-dev@openjdk.org <core-libs-dev@openjdk.org>
Subject: Gatherer JavaDoc

Hi, I have trio of minor questions about the Gatherer JavaDoc at 
https://download.java.net/java/early_access/jdk25/docs/api/java.base/java/util/stream/Gatherer.html

1. "Gatherers whose integrator is an instance of Gatherer.Integrator.Greedy can 
be assumed not to short-circuit, *and the return value of invoking 
Gatherer.Integrator.integrate(Object, Object, Downstream) does not need to be 
inspected*."

The way it is worded, I get the impression that a greedy integrator could 
simply return false (or to save a letter, true), because, not inspected. But I 
am confused. It was my impression that any integrator, greedy or not, should 
return false if downstream.push returns false. Why would the implementation not 
want to know? (The current implementation does inspect the return value.)

2. "Gatherers whose finisher is defaultFinisher() are considered to not have an 
end-of-stream hook *and invoking their finisher is optional.*"

I don't get the significance of the "and" part. Why would anyone care if 
defaultFinisher is invoked? It's a no-op.

3. What is the use case for

static <T,R> Gatherer<T,Void,R>
of(Gatherer.Integrator<Void,T,R> integrator, BiConsumer<Void, 
Gatherer.Downstream<? super R>> finisher)

If there is no state, what can the finisher do?

Thanks,

Cay

--

Cay S. Horstmann | https://horstmann.com

Reply via email to