Hello, Sorry I didn't respond when I said I was going to. I have been juggling some pretty severe personal emergencies. So, not only am I overdue on this, but I don't really have the energy to make the full post I originally wanted to.
Regardless, I have made a new thread posting my findings, and why I think this new windowBy function makes sense. Here is the link -- https://mail.openjdk.org/pipermail/core-libs-dev/2024-August/127293.html Thank you for your time and patience! David Alayachew On Sun, Jan 28, 2024 at 1:54 AM David Alayachew <davidalayac...@gmail.com> wrote: > Thank you both for your replies! > > And thanks for the Gatherer example Viktor. > > It sounds like, from your email, that you want to see just how useful this > method would be to add before we can justify adding it to Gatherers. > > Fair enough. I have spent a couple of days using this custom Gatherer you > made for me, and I will post a new email thread either tomorrow or the day > after that shows my experience with it. My hope is that I can convince you > that this function absolutely is worth adding. > > Thank you for your time and help! > David Alayachew > > On Wed, Jan 10, 2024 at 2:29 PM Viktor Klang <viktor.kl...@oracle.com> > wrote: > >> >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) ? >> >> No, that was just a (benign) omission from typing the solution as I was >> typing the email 🙂 >> >> >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) >> >> Great question! >> I chose to do that since I wanted to A) allocate the backing list >> on-demand, and also B) not allocate a new ArrayList for the downstream >> windows and retain the (cleared) old one (since its size could become >> needlessly large). >> >> >> As a side-note, I tend to prototype using lambdas and then refactor >> as/when needed to either embed logic in the state or even migrate into a >> full-on implementation of the Gatherer interface (for instance if I want to >> override composition). >> >> Cheers, >> √ >> >> >> *Viktor Klang* >> Software Architect, Java Platform Group >> Oracle >> >> >> ------------------------------ >> *From:* Remi Forax <fo...@univ-mlv.fr> >> *Sent:* Wednesday, 10 January 2024 19:16 >> *To:* Viktor Klang <viktor.kl...@oracle.com> >> *Cc:* David Alayachew <davidalayac...@gmail.com>; core-libs-dev < >> core-libs-dev@openjdk.org> >> *Subject:* [External] : Re: Gatherers -- conditionalWindowFixed? >> >> >> >> ------------------------------ >> >> *From: *"Viktor Klang" <viktor.kl...@oracle.com> >> *To: *"David Alayachew" <davidalayac...@gmail.com>, "core-libs-dev" < >> core-libs-dev@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-r...@openjdk.org> on behalf of >> David Alayachew <davidalayac...@gmail.com> >> *Sent:* Wednesday, 10 January 2024 07:05 >> *To:* core-libs-dev@openjdk.org <core-libs-dev@openjdk.org> >> *Subject:* Gatherers -- conditionalWindowFixed? >> >> Hello Core Libs Dev Team, >> >> I have been reading through JEP 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 >> >>