Gatherers -- conditionalWindowFixed?

Remi Forax forax at univ-mlv.fr
Wed Jan 10 18:16:55 UTC 2024


> From: "Viktor Klang" <viktor.klang at oracle.com>
> To: "David Alayachew" <davidalayachew at gmail.com>, "core-libs-dev"
> <core-libs-dev at openjdk.org>
> Sent: Wednesday, January 10, 2024 2:33:45 PM
> Subject: Re: Gatherers -- conditionalWindowFixed?

> Hi David!

> Apologies for the late reply, there's been lots of catching up to do after the
> holidays.

> >I'm really excited for what this will enable for us.

> I'm really glad to hear that \uD83D\uDE42

> >It is very much appreciated.

> \uD83D\uDC4D

>> Could we add one more method for a conditionalWindowFixed? We would need to pass
>> in some Predicate<T>. If the predicate returns true, create a list (if it does
>> not already exist) then add the element to it. If the predicate returns false
>> while the list is empty, then just move along to the next. Else if the
>> predicate returns false while the list is non empty, pass the list down into
> > the stream. So, you end up with Stream<T> -----> Stream<List<T>>.

> What ends up under Gatherers.* does require careful triaging, ideally by first
> seeing user-created implementations being heavily used/useful, then potential
> candidate for Gatherers.*, and then at the end it might end up in Stream as a
> dedicated method.

> By virtue of the Gatherers API, it seems pretty straight-forward for you to
> implement what you describe, and personally I'd probably call it something like
> windowBy .

> Just typing this up as I write this reply, it could look something like this:

> <TR> Gatherer<TR, ?, List<TR>> windowBy(Predicate<TR> includeInCurrentWindow) {
> class State {
> ArrayList<TR> window;

> boolean integrate(TR element, Gatherer.Downstream<? super List<TR>> downstream)
> {
> if (window != null && !includeInCurrentWindow.test(element)) {
> var result = Collections.unmodifiableList(window);
> window = null;
> if (!downstream.push(result))
> return false;
> }

> if (window == null)
> window = new ArrayList<>();
> return window.add(element);
> }

> void finish(Gatherer.Downstream<? super List<TR>> downstream) {
> if (window != null) {
> var result = Collections.unmodifiableList(window);
> window = null;
> downstream.push(result);
> }
> }
> }
> return Gatherer.<TR, State, List<TR>>ofSequential(State::new, State::integrate,
> State::finish);
> }

> jshell> Stream.of("header", "value1", "value2", "header", "header", "value 3",
> "value 4", null).gather(windowBy(Predicate.not("header"::equals))).toList()
> $1 ==> [[header, value1, value2], [header], [header, value 3, value 4, null]]

Hello, 
I've two questions, 
1/ Is there a reason why the integrator is not declared greedy (I'm still not sure to what exactly Greedy means in the context of gatherers) ? 
2/ Is there a reason to write the code in a OOP way like you have done instead of only having fields in State and specify the behaviors using lambdas (because with lambdas will you get inference) 

<T> Gatherer<T, ?, List<T>> windowBy(Predicate<? super T> includeInCurrentWindow) { 
class State { 
ArrayList<T> window; 
} 
return Gatherer.ofSequential( 
State::new, 
(state, element, downstream) -> { 
... 
}, 
(state, downstream) -> { 
... 
}); 
} 

> Cheers,
>
regards, 
Rémi 

> Viktor Klang
> Software Architect, Java Platform Group
> Oracle

> From: core-libs-dev <core-libs-dev-retn at openjdk.org> on behalf of David
> Alayachew <davidalayachew at gmail.com>
> Sent: Wednesday, 10 January 2024 07:05
> To: core-libs-dev at openjdk.org <core-libs-dev at openjdk.org>
> Subject: Gatherers -- conditionalWindowFixed?
> Hello Core Libs Dev Team,

> I have been reading through JEP 461 ( [ https://openjdk.org/jeps/461 |
> https://openjdk.org/jeps/461 ] ) about Gatherers, and I'm really excited for
> what this will enable for us.

> By far, the most important functionality that this API facilitates is the
> ability to create windows. Anytime I needed a window, I was basically forced to
> use a for loop. Now, the 2 most common window cases are being handed to us for
> free. It is very much appreciated.

> Could we add one more method for a conditionalWindowFixed? We would need to pass
> in some Predicate<T>. If the predicate returns true, create a list (if it does
> not already exist) then add the element to it. If the predicate returns false
> while the list is empty, then just move along to the next. Else if the
> predicate returns false while the list is non empty, pass the list down into
> the stream. So, you end up with Stream<T> -----> Stream<List<T>>.

> The reason I think this is worth adding is because it facilitates a really
> common use case. We may not want all windows to be the same size.

> Is this something worth adding to the Gatherers API?

> Thank you for your time and help!
> David Alayachew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20240110/311cafc8/attachment.htm>


More information about the core-libs-dev mailing list