<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 style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Thank you for sharing your practical experience with Gatherers, Olexandr—it is much appreciated!</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<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">
Some thoguhts while reading your email:</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<ul style="margin-top: 0px; margin-bottom: 0px; list-style-type: disc;" data-editing-info="{"applyListStyleFromLevel":false,"unorderedStyleType":1}">
<li style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div role="presentation" class="elementToProof">Given that your custom Gatherers shown never short-circuit, you might find it performance-wise valuable to instantiate then with Gatherer.Integrator.ofGreedy.</div>
</li></ul>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<ul style="margin-top: 0px; margin-bottom: 0px; list-style-type: disc;" data-editing-info="{"applyListStyleFromLevel":false,"unorderedStyleType":1}">
<li style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<div role="presentation" class="elementToProof">For your finishers, I've personally found it valuable to short-circuit of the downstream push returns false, so in the cases above it'd be something like</div>
</li></ul>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<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">
        If (!downstream.push(element))<br>
            return;</div>
<div class="elementToProof" id="Signature">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Cheers,<br>
√</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<b><br>
</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<b>Viktor Klang</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Software Architect, Java Platform Group<br>
Oracle</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="text-align: left; margin-left: 5pt; font-family: Calibri; font-size: 10pt; color: rgb(0, 0, 0);" class="elementToProof">
Confidential – Oracle Internal</div>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> core-libs-dev <core-libs-dev-retn@openjdk.org> on behalf of Olexandr Rotan <rotanolexandr842@gmail.com><br>
<b>Sent:</b> Friday, 17 October 2025 20:45<br>
<b>To:</b> core-libs-dev <core-libs-dev@openjdk.org><br>
<b>Subject:</b> My expirience with gatherers</font>
<div> </div>
</div>
<div>
<div dir="ltr">Greetings to the core libs folks. I have been using Gatherers extensively for my job in a past few months, and would like to share some of the gatherers that I have been extensively using, so maybe some of them may be a source of inspiration
 for evolving the Gatherers class.<br>
<br>
1. eagerlyConsume()<br>
Implementation:
<div>
<div style="background-color:rgb(30,31,34); color:rgb(188,190,196)">
<pre style="font-family:"JetBrains Mono",monospace"><span style="color:rgb(207,142,109)">public static </span><<span style="color:rgb(22,186,172)">T</span>> Gatherer<<span style="color:rgb(22,186,172)">T</span>, ?, <span style="color:rgb(22,186,172)">T</span>> <span style="color:rgb(86,168,245)">eagerlyConsume</span>() {<br>    <span style="color:rgb(207,142,109)">return </span>Gatherer.<span style="font-style:italic">of</span>(<br>        ArrayList<<span style="color:rgb(22,186,172)">T</span>>::<span style="color:rgb(207,142,109)">new</span>,<br>        (list, val, downstream) -> {<br>            list.add(val);<br>            <span style="color:rgb(207,142,109)">return true</span>;<br>        },<br>        (left, right) -> {<br>            left.addAll(right);<br>            <span style="color:rgb(207,142,109)">return </span>left;<br>        },<br>        (list, downstream) -> {<br>            <span style="color:rgb(207,142,109)">for </span>(<span style="color:rgb(207,142,109)">var </span>item : list) {<br>                downstream.push(item);<br>            }<br>        }<br>    );<br>}</pre>
</div>
</div>
<div>Purpose: many times, i need to perform a concurrent mapping of jpa entities to dtos. Unfortunately, mapConcurrent does not accept custom executors, which i need in order to propagate auth, transaction and other contexts. So, therefore, I previously have
 used following pattern:<br>
<br>
stream().map(COmpletableFuture.supplyAsync(..., executor)).toList().stream().map(CompletableFuture::join)<br>
<br>
toList is required here to eagerly start all futures, as otherwise the will actually launch sequentially due to the pulling nature of streams. With gatherer, on the other hand, i can achieve following:<br>
stream().map(COmpletableFuture.supplyAsync(..., executor))..gather<font color="#000000" face="arial, sans-serif">(eagerlyConsume())</font> .map(CompletableFuture::join), which looks much more readable, and (presumably, haven't actually verified it) should have
 better performance<br>
<br>
2. ofCollector<br>
Implementation:<br>
<div style="background-color:rgb(30,31,34); color:rgb(188,190,196)">
<pre style="font-family:"JetBrains Mono",monospace"><span style="color:rgb(207,142,109)">public </span><<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, <span style="color:rgb(22,186,172)">R</span>> Gatherer<<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, <span style="color:rgb(22,186,172)">R</span>> <span style="color:rgb(86,168,245)">ofCollector</span>(Collector<<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, <span style="color:rgb(22,186,172)">R</span>> collector) {<br>    <span style="color:rgb(207,142,109)">return </span>Gatherer.<span style="font-style:italic">of</span>(<br>        collector.supplier(),<br>        (a, t, _) -> {<br>            <span style="color:rgb(199,125,187)">collector</span>.accumulator().accept(a, t);<br>            <span style="color:rgb(207,142,109)">return true</span>;<br>        },<br>        collector.combiner(),<br>        (state, downstream) -> downstream.push(<span style="color:rgb(199,125,187)">collector</span>.finisher().apply(state))<br>    );<br>}</pre>
</div>
Pretty self explanatory, this is just an adapter of collector to gatherer, allowing arbitrary collector-defined folds<br>
<br>
3. collectThenFlatten & co<br>
Implementations:<br>
</div>
<div>
<div style="background-color:rgb(30,31,34); color:rgb(188,190,196)">
<pre style="font-family:"JetBrains Mono",monospace"><span style="color:rgb(207,142,109)">public static </span><<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, <span style="color:rgb(22,186,172)">R </span><span style="color:rgb(207,142,109)">extends </span>Collection<<span style="color:rgb(22,186,172)">T</span>>> Gatherer<<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, <span style="color:rgb(22,186,172)">T</span>> <span style="color:rgb(86,168,245)">collectThenFlatten</span>(Collector<<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, <span style="color:rgb(22,186,172)">R</span>> collector) {<br>    <span style="color:rgb(207,142,109)">return </span>Gatherer.<span style="font-style:italic">of</span>(<br>        collector.supplier(),<br>        (a, t, _) -> {<br>            <span style="color:rgb(199,125,187)">collector</span>.accumulator().accept(a, t);<br>            <span style="color:rgb(207,142,109)">return true</span>;<br>        },<br>        collector.combiner(),<br>        (state, downstream) -> {<br>            <span style="color:rgb(207,142,109)">for </span>(<span style="color:rgb(207,142,109)">var </span>item : <span style="color:rgb(199,125,187)">collector</span>.finisher().apply(state)) {<br>                downstream.push(item);<br>            }<br>        }<br>    );<br>}<br><br><span style="color:rgb(207,142,109)">public static </span><<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, <span style="color:rgb(22,186,172)">K</span>, <span style="color:rgb(22,186,172)">V</span>, <span style="color:rgb(22,186,172)">R </span><span style="color:rgb(207,142,109)">extends </span>Map<<span style="color:rgb(22,186,172)">K</span>, <span style="color:rgb(22,186,172)">V</span>>> Gatherer<<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, Map.Entry<<span style="color:rgb(22,186,172)">K</span>, <span style="color:rgb(22,186,172)">V</span>>> <span style="color:rgb(86,168,245)">collectThenFlattenEntries</span>(Collector<<span style="color:rgb(22,186,172)">T</span>, <span style="color:rgb(22,186,172)">A</span>, <span style="color:rgb(22,186,172)">R</span>> collector) {<br>    <span style="color:rgb(207,142,109)">return </span>Gatherer.<span style="font-style:italic">of</span>(<br>        collector.supplier(),<br>        (a, t, _) -> {<br>            <span style="color:rgb(199,125,187)">collector</span>.accumulator().accept(a, t);<br>            <span style="color:rgb(207,142,109)">return true</span>;<br>        },<br>        collector.combiner(),<br>        (state, downstream) -> {<br>            <span style="color:rgb(207,142,109)">for </span>(<span style="color:rgb(207,142,109)">var </span>entry : <span style="color:rgb(199,125,187)">collector</span>.finisher().apply(state).entrySet()) {<br>                downstream.push(entry);<br>            }<br>        }<br>    );<br>}</pre>
</div>
</div>
<div>These are more specialized adapters of collector adapters, mostly a convenience for avoiding flatMapping results, THough, I would like to note that <font face="arial, sans-serif" color="#000000" style="">collectThenFlattenEntries is mostly used specifically
 with groupingBy collector, to avoid following nasty chains:<br>
<br>
collect(groupingBy(...)).entrySet().stream()<br>
<br>
Maybe it's just my personal preferences, but i really dislike this back n forth from stream to map, then to set and to stream again, so this gatherer seems pretty pleasant to use<br>
<br>
That's basically all that I wanted to share regarding this topic, hope this experience will have some value for core libs maintainers<br>
<br>
Best regards</font></div>
</div>
</div>
</body>
</html>