<div dir="ltr"><div class="gmail_default" style="font-family:monospace">Hello <a class="gmail_plusreply" id="plusReplyChip-0" href="mailto:core-libs-dev@openjdk.org" tabindex="-1">@core-libs-dev</a>,</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">This is a follow up of one of my previous experience reports, a little over a year ago.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace"><a href="https://mail.openjdk.org/pipermail/core-libs-dev/2024-August/127293.html">https://mail.openjdk.org/pipermail/core-libs-dev/2024-August/127293.html</a></div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Just wanted to report more of my positive experiences with Gatherers, specifically with a custom Gatherer that <a class="gmail_plusreply" id="plusReplyChip-1" href="mailto:viktor.klang@oracle.com" tabindex="-1">@Viktor Klang</a> made for me called windowBy. Here is the implementation below.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace"><TR> Gatherer<TR, ?, List<TR>> windowBy(Predicate<TR> includeInCurrentWindow) {<br>    class State {<br>        ArrayList<TR> window;<br>    <br>        boolean integrate(TR element, Gatherer.Downstream<? super List<TR>> downstream) {<br>            if (window != null && !includeInCurrentWindow.test(element)) {<br>                var result = Collections.unmodifiableList(window);<br>                window = null;<br>                if (!downstream.push(result))<br>                    return false;<br>            }<br>        <br>            if (window == null)<br>                window = new ArrayList<>();<br>          <br>            return window.add(element);<br>        }<br>    <br>        void finish(Gatherer.Downstream<? super List<TR>> downstream) {<br>            if (window != null) {<br>                var result = Collections.unmodifiableList(window);<br>                window = null;<br>                downstream.push(result);<br>            }<br>        }<br>    }<br>    return Gatherer.<TR, State, List<TR>>ofSequential(State::new, State::integrate, State::finish);<br>}</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Clean and simple.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Anyways, as for my experience report, a found a brand new way to use this custom Gatherer -- event coalescing.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Sometimes, if consecutive events being streamed are of the same type, then to reduce computation, you might be able to avoid doing more work by grouping together the potential duplicates, then handling them separately in a coalescing path. I'd much rather solve that problem than a caching problem lol.</div><div class="gmail_default" style="font-family:monospace"><br></div><div class="gmail_default" style="font-family:monospace">Anyways, here are the 2 examples where it served me well.</div><br><div class="gmail_default" style="font-family:monospace"><ol><li>Network Request Coalescing.</li><ol><li>When checking the availability of certain networks, I am now able to save some bandwidth by combining multiple, consecutive requests within a certain time to a certain network. And since I am definitely bandwidth bound, that helps. Nothing I couldn't do before, but keeping it within Streams allowed me to avoid ripping out my old solution when it stopped being a good fit. I wish I could share the code, but it's not my right to share it.</li></ol><li>Path-Finding Algorithm -- Clustering</li><ol><li>This one is still a work in progress, so I may be speaking prematurely here. But I was so impressed that this is working thus far. Long story short, I am building a path-finding algorithm where, if a set of points are close enough together, then they can be serviced as a group, and thus, lower the total weight of servicing those nodes, as opposed to servicing them individually. Again, not done yet, so I might be jumping the gun, but it worked so well for me out of the box, that I thought it was worth sharing.</li></ol></ol><div>Hopefully this bumps up windowBy on the triage list of potential pre-built gatherers to add to the standard library. And thanks again to Viktor and friends for putting this Gatherers library together -- it's a great addition!</div><div><br></div><div>Thank you all for your time and consideration!</div><div>David Alayachew</div></div></div>