JDK-8343323 : Prepare Gatherers for graduation from Preview
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.util.stream
  • Priority: P4
  • Status: Provisional
  • Resolution: Unresolved
  • Fix Versions: 24
  • Submitted: 2024-10-30
  • Updated: 2024-11-01
Related Reports
CSR :  
Description
Summary
-------

Introduces `Stream::gather(Gatherer)`, the `java.util.stream.Gatherer` interface, and the class for built-in Gatherer operations named `java.util.stream.Gatherers`. The feature has been in preview for 2 releases. It is proposed to be permanent API with no changes from last preview except to drop the preview annotation and bump the since tag.

Problem
-------

`java.util.stream.Stream` does not have an intermediate operation which allows to serve as a vehicle for implementing generic user-defined intermediate operations.

Solution
--------

We introduce `java.util.stream.Stream::gather(Gatherer)` as the entry-point for attaching user-defined intermediate operations -- "Stream Gatherers".  In order to ensure binary compatibility, a default implementation of this method is provided.

We also define the `java.util.stream.Gatherer` interface, which allows the Java Standard Library, and Java developers, to implement new intermediate operations that can be attached to `java.util.stream.Stream` using the `gather(Gatherer)`-method. Gatherer's API design is heavily inspired by `java.util.stream.Collector`, and the runtime evaluation thereof draws from existing implementations in the JDK.

In order to provide built-in Gatherers to Java developers, the `java.util.stream.Gatherers` class is introduced, which exposes the following public static methods: `fold`, `mapConcurrent`, `scan`, `windowFixed`, `windowSliding` -- and all of them return a Gatherer describing that respective operation given a set of parameter values.

Alternatives have been discussed [here](https://cr.openjdk.org/~vklang/Gatherers.html).

Specification
-------------

See attached zip archive.

For more details, see: https://github.com/openjdk/jdk/pull/21686
Comments
[~alanb], [~liach], opinions differ -- I will concede to is a common practice for the per-method type variables to shadow the names of the type variables for the enclosing type, but I think that is confusing in a different way.
01-11-2024

[~vklang], up to you where the null-handling statement goes, on the interface or per-method. If there is a convention on that point in the wider streams API, I recommend following that.
01-11-2024

> In a generic type like Gatherer.Integrator that defines `static` methods, I recommend using distinct names for the type variables on the method vs the type. I think reusing the same type variable name for static factory methods as on the type itself has been a standard and accepted practice. It feels just like the diamond constructor call, and such is already the case in widely used `<E> List.of(E...)`, `<K, V> Map.of(K, V)` factories. `Gatherer.Integrator` simplify follows this established trend.
01-11-2024

There are different views on this but I think some people do finding it confusing when there are several type variables and the static methods uses different names to the type.
01-11-2024

[~darcy] Thanks for the input! Hoisting the NPE specification section could make sense, I wanted to keep the spec close to the definition site to avoid the situation where there's a mismatch—do you prefer I make this change? Introducing distinct type variable names on statics vs their containing parameterized type could absolutely make sense, in this case I kept names the same to clearly indicate how they end up / how they relate to the parameterized type—it seemed like established practice (one recent example: List<E> vs List.<E>of()). Happy to change if it improves the user experience!
01-11-2024

Moving to Provisional, not Approved. A few PR-level comments for your consideration: In Gatherer, you could promote the "throw NPE if any argument is null" statement to an interface-level statement rather than a method-level one. In a generic type like Gatherer.Integrator<A,T,R> that defines _static_ methods, I recommend using distinct names for the type variables on the method vs the type.
01-11-2024

[~liach] [~darcy] I replaced the original zip archive (containing java source files with the javadoc html pages for said files) and updated the description to indicate that the feature has been previewed 2 times prior and there has been little in terms of changes throughout the preview process.
31-10-2024

Looks good. Changed the scope to SE as this is part of the java. APIs.
30-10-2024

There has been 0 API changes throughout the JEP lifecycle (461, 473, 485) and the only changes are documentation fixes and correctness-related.
30-10-2024