<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div class="">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1">
>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) ?<br>
<br>
No, that was just a (benign) omission from typing the solution as I was typing the email
<span id="🙂">🙂</span><br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1">
<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1 ContentPasted2">
>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)<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1 ContentPasted2">
<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1 ContentPasted2">
Great question!</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1 ContentPasted2">
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).<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1 ContentPasted2">
<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1 ContentPasted2">
<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1 ContentPasted2">
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).<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted1 ContentPasted2">
<br>
</div>
<div id="Signature">
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="ContentPasted0">
Cheers,<br class="ContentPasted0">
√</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br class="ContentPasted0">
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<b><br class="ContentPasted0">
</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<b class="ContentPasted0">Viktor Klang</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="ContentPasted0">
Software Architect, Java Platform Group<br class="ContentPasted0">
Oracle</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
</div>
</div>
</div>
<div id="appendonsend"></div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="divRplyFwdMsg" dir="ltr"><font style="font-size: 11pt; color: rgb(0, 0, 0);" face="Calibri, sans-serif"><b>From:</b> Remi Forax <forax@univ-mlv.fr><br>
<b>Sent:</b> Wednesday, 10 January 2024 19:16<br>
<b>To:</b> Viktor Klang <viktor.klang@oracle.com><br>
<b>Cc:</b> David Alayachew <davidalayachew@gmail.com>; core-libs-dev <core-libs-dev@openjdk.org><br>
<b>Subject:</b> [External] : Re: Gatherers -- conditionalWindowFixed?</font>
<div> </div>
</div>
<div>
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div><br>
</div>
<div><br>
</div>
<hr id="x_zwchr" data-marker="__DIVIDER__">
<div data-marker="__HEADERS__">
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<b>From: </b>"Viktor Klang" <viktor.klang@oracle.com><br>
<b>To: </b>"David Alayachew" <davidalayachew@gmail.com>, "core-libs-dev" <core-libs-dev@openjdk.org><br>
<b>Sent: </b>Wednesday, January 10, 2024 2:33:45 PM<br>
<b>Subject: </b>Re: Gatherers -- conditionalWindowFixed?<br>
</blockquote>
</div>
<div></div>
<div data-marker="__QUOTED_TEXT__">
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div class="x_elementToProof x_ContentPasted0" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Hi David!<br>
<br>
Apologies for the late reply, there's been lots of catching up to do after the holidays.<br>
<br>
>I'm really excited for what this will enable for us.<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
I'm really glad to hear that <span id="x_🙂">\uD83D\uDE42</span><br>
<br>
>It is very much appreciated.<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span id="x_👍">\uD83D\uDC4D</span><br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_ContentPasted1 x_ContentPasted2" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
> 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>>.<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
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.</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
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
<i>windowBy</i>.</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Just typing this up as I write this reply, it could look something like this:</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_ContentPasted1 x_ContentPasted6" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<TR> Gatherer<TR, ?, List<TR>> windowBy(Predicate<TR> includeInCurrentWindow) {
<div class="x_ContentPasted6">  class State {</div>
<div class="x_ContentPasted6">    ArrayList<TR> window;</div>
<div><br class="x_ContentPasted6">
</div>
<div class="x_ContentPasted6">    boolean integrate(TR element, Gatherer.Downstream<? super List<TR>> downstream) {</div>
<div class="x_ContentPasted6">      if (window != null && !includeInCurrentWindow.test(element)) {</div>
<div class="x_ContentPasted6">        var result = Collections.unmodifiableList(window);</div>
<div class="x_ContentPasted6">        window = null;</div>
<div class="x_ContentPasted6">        if (!downstream.push(result))</div>
<div class="x_ContentPasted6">          return false;</div>
<div class="x_ContentPasted6">      }</div>
<div><br class="x_ContentPasted6">
</div>
<div class="x_ContentPasted6">      if (window == null)</div>
<div class="x_ContentPasted6">        window = new ArrayList<>();</div>
<div class="x_ContentPasted6">      </div>
<div class="x_ContentPasted6">      return window.add(element);</div>
<div class="x_ContentPasted6">    }</div>
<div><br class="x_ContentPasted6">
</div>
<div class="x_ContentPasted6">    void finish(Gatherer.Downstream<? super List<TR>> downstream) {</div>
<div class="x_ContentPasted6">      if (window != null) {</div>
<div class="x_ContentPasted6">        var result = Collections.unmodifiableList(window);</div>
<div class="x_ContentPasted6">        window = null;</div>
<div class="x_ContentPasted6">        downstream.push(result);</div>
<div class="x_ContentPasted6">      }</div>
<div class="x_ContentPasted6">    }</div>
<div class="x_ContentPasted6">  }</div>
<div class="x_ContentPasted6">  return Gatherer.<TR, State, List<TR>>ofSequential(State::new, State::integrate, State::finish);</div>
}<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_ContentPasted1 x_ContentPasted3 x_ContentPasted5" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
jshell> Stream.of("header", "value1", "value2", "header", "header", "value 3", "value 4", null).gather(windowBy(Predicate.not("header"::equals))).toList()<br class="x_ContentPasted5">
$1 ==> [[header, value1, value2], [header], [header, value 3, value 4, null]]<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
</div>
</div>
</blockquote>
<div><br>
</div>
<div>Hello,<br data-mce-bogus="1">
</div>
<div>I've two questions,<br data-mce-bogus="1">
</div>
<div>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) ?<br data-mce-bogus="1">
</div>
<div>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)<br data-mce-bogus="1">
</div>
<div><br data-mce-bogus="1">
</div>
<div><T> Gatherer<T, ?, List<T>> windowBy(Predicate<? super T> includeInCurrentWindow) {<br data-mce-bogus="1">
</div>
<div>
<div class="x_ContentPasted6">  class State {</div>
<div class="x_ContentPasted6">    ArrayList<T> window;</div>
<div class="x_ContentPasted6">  }<br data-mce-bogus="1">
</div>
<div class="x_ContentPasted6">  return Gatherer.ofSequential(</div>
<div class="x_ContentPasted6">      State::new,<br data-mce-bogus="1">
</div>
<div class="x_ContentPasted6">      (state, element, downstream) -> {<br data-mce-bogus="1">
</div>
<div class="x_ContentPasted6">       ...<br data-mce-bogus="1">
</div>
<div class="x_ContentPasted6">      },<br data-mce-bogus="1">
</div>
<div class="x_ContentPasted6">      (state, downstream) -> {<br data-mce-bogus="1">
</div>
<div class="x_ContentPasted6">        ...<br data-mce-bogus="1">
</div>
<div class="x_ContentPasted6">      });<br data-mce-bogus="1">
</div>
<div>}   <br>
</div>
</div>
<div><br data-mce-bogus="1">
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div class="x_ContentPasted1" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="x_Signature">
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Cheers,<br>
√</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>regards,<br data-mce-bogus="1">
</div>
<div>Rémi<br data-mce-bogus="1">
</div>
<div><br data-mce-bogus="1">
</div>
<blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div class="x_elementToProof">
<div id="x_Signature">
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<b><br>
</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<b>Viktor Klang</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Software Architect, Java Platform Group<br>
Oracle<br>
</div>
</div>
</div>
</div>
<hr style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font style="font-size: 11pt; color: rgb(0, 0, 0);" face="Calibri, sans-serif"><b>From:</b> core-libs-dev <core-libs-dev-retn@openjdk.org> on behalf of David Alayachew <davidalayachew@gmail.com><br>
<b>Sent:</b> Wednesday, 10 January 2024 07:05<br>
<b>To:</b> core-libs-dev@openjdk.org <core-libs-dev@openjdk.org><br>
<b>Subject:</b> Gatherers -- conditionalWindowFixed?</font>
<div> </div>
</div>
<div>
<div dir="ltr">
<div class="x_x_gmail_default" style="font-family:monospace">Hello Core Libs Dev Team,<br>
<br>
I have been reading through JEP 461 (<a href="https://openjdk.org/jeps/461" data-auth="NotApplicable" id="OWA4aedc79b-5bff-f738-0eb6-be35009f56cf" class="OWAAutoLink" data-loopstyle="linkonly">https://openjdk.org/jeps/461</a>) about Gatherers, and I'm really
 excited for what this will enable for us.<br>
<br>
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.<br>
<br>
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>>.<br>
<br>
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.<br>
<br>
Is this something worth adding to the Gatherers API?<br>
<br>
Thank you for your time and help!<br>
David Alayachew<br>
</div>
</div>
</div>
<br>
</blockquote>
</div>
</div>
</div>
</body>
</html>