<div dir="ltr"><div dir="ltr">Hi Viktor,</div><p>Thank you for the detailed explanation and the links to the Javadoc for <code>findFirst()</code> and <code>limit()</code>. You're absolutely correct in your characterization of these operations – they are indeed concerned with encounter order, and parallel execution doesn't inherently change that unless the stream is explicitly unordered. I want to clarify a few of my points that I didn't explain clearly (see below).</p><p><br></p><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Wed, Jun 4, 2025 at 7:38 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com">viktor.klang@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="msg1559302929934323246">




<div dir="ltr">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Hi Jige,<br>
<br>
First of all—you're most welcome. Thanks for your insightful questions.<br>
<br>
</div>
<div style="font-size:12pt;color:rgb(0,0,0)"><span style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif">></span><span style="background-color:rgb(255,255,255)"><b>Temptation
 for Race Semantics:</b> The beauty of </span><span style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;background-color:rgb(255,255,255)"><code>mapConcurrent()</code></span><span style="background-color:rgb(255,255,255)"> integrating
 with the Stream API means developers will naturally be drawn to use it for race-like scenarios. Operations like
</span><span style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;background-color:rgb(255,255,255)"><code>findFirst()</code></span><span style="background-color:rgb(255,255,255)"> or
</span><span style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;background-color:rgb(255,255,255)"><code>limit(N)</code></span><span style="background-color:rgb(255,255,255)"> to
 get the first few completed results are very intuitive combinations.</span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)"><br>
</span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)">It's important to distinguish between spatial (encounter) order and temporal (availability) order.</span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)"><br>
</span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)">If we look at `Stream::findFirst()` we see:<br>
<br>
</span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)">«Returns an </span><span style="font-family:"DejaVu Sans Mono",monospace;color:rgb(74,103,130);background-color:rgb(255,255,255)"><code style="font-family:"DejaVu Sans Mono",monospace"><a href="https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/Optional.html" id="m_1559302929934323246OWA08bcdc9d-1ae1-1e01-28ea-5ac396af6e08" title="class in java.util" style="color:rgb(74,103,130);background-color:rgb(255,255,255);text-align:left" target="_blank">Optional</a></code></span><span style="background-color:rgb(255,255,255)"> describing
 the first element of this stream, or an empty </span><span style="font-family:"DejaVu Sans Mono",monospace;background-color:rgb(255,255,255)"><code style="font-family:"DejaVu Sans Mono",monospace">Optional</code></span><span style="background-color:rgb(255,255,255)"> if
 the stream is empty. If the stream has no encounter order, then any element may be returned.» -
<a href="https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Stream.html#findFirst()" id="m_1559302929934323246LPlnk153964" target="_blank">
https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Stream.html#findFirst()</a></span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)"><br>
</span></div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
And if we look at `Stream::limit(long)` we see:<br>
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<i>«While limit() is generally a cheap operation on sequential stream pipelines, it can be quite expensive on ordered parallel pipelines, especially for large values of maxSize, since limit(n) is constrained to return not just any n elements, but
</i><b><i>the first n elements in the encounter order</i></b><i>. » (emphasis mine) -
<a href="https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Stream.html#limit(long)" id="m_1559302929934323246LPlnk802238" target="_blank">
https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Stream.html#limit(long)</a></i></div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
So, we can conclude that "first" and "limit" are about <b>encounter order</b>, and we can conclude that the presence of parallel does not change that—only "unorderedness"
<b><i>may</i></b> change that.</div></div></div></blockquote><div><br></div><div><br></div><div><p>My apologies if my previous example using <code>findFirst()</code> wasn't as clear as it could have been. I'd like to clarify how I see the interaction with <code>mapConcurrent()</code> playing out:</p><ol>
<li>
<p><strong><code>mapConcurrent()</code>'s Influence on Encounter Order:</strong> When I mentioned using <code>findFirst()</code> (or <code>limit()</code>) for race semantics, the implicit assumption was how <code>mapConcurrent()</code> would feed elements into these terminal operations. The "encounter order" that <code>findFirst()</code> sees is precisely what <code>mapConcurrent()</code> emits. If <code>mapConcurrent()</code> emits results strictly according to input order, then <code>findFirst()</code> will respect that. However, if an unordered <code>mapConcurrent()</code> were to emit results in their temporal order of completion, then <code>findFirst()</code> would naturally pick the first one that <em>actually finished</em>, effectively achieving a race. My point is that <code>mapConcurrent()</code> is in a position to define the encounter order that downstream operations like <code>findFirst()</code> will act upon. The surprise isn't with <code>findFirst()</code>'s definition, but with how a strictly ordered <code>mapConcurrent()</code> might prevent it from being used effectively for "first-to-finish" logic.</p>
</li>
<li>
<p><strong>The Role of <code>findAny()</code>:</strong> You're right that my example using findFirst() was more nuanced than I intuitively assumed. A developer well-versed in the Stream API nuances might indeed opt for <code>findAny()</code> to implement race semantics, especially given its Javadoc explicitly mentioning suitability for "maximal performance in parallel operations." <code>findAny()</code> is designed to return <em>any</em> element, which aligns well with picking the temporally first available result from an unordered concurrent process.</p>
</li>
<li>
<p><strong>Aligning Spec with Intuition:</strong> My broader concern is about the intuitive use of these powerful new tools. If <code>mapConcurrent()</code> maintains strict input ordering, it's a perfectly valid and understandable specification by itself. However, the potential for surprise arises when developers, especially those less acquainted with every fine print of stream ordering, attempt to combine <code>mapConcurrent()</code> with <code>findFirst()</code> or <code>findAny()</code> to build common concurrent utilities like a race. They might intuitively expect that "concurrent mapping" followed by "find first/any" would yield the result that completes earliest. While developers <i>should</i> read all related documentation, there's also a design ideal where the API's behavior aligns closely with reasonable developer intuition, especially for common patterns. An unordered <code>mapConcurrent()</code> (or an option for it) would, in my view, better support this intuitive use for race-like patterns. Whereas, I have my doubts that developers commonly would intuitively assume a concurrent operation to stick to strict ordering (it's not what we are used to in most concurrent or multil-threading scenarios)</p>
</li>
</ol><p>Ultimately, the question is whether <code>mapConcurrent()</code> should be optimized primarily for preserving input sequence, or for enabling maximum throughput and flexibility in concurrent scenarios, including efficient "first-to-finish" patterns.</p></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="msg1559302929934323246"><div dir="ltr">
<div id="m_1559302929934323246Signature">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-size:12pt;color:rgb(0,0,0)"><span style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif">></span><span style="background-color:rgb(255,255,255)"><b>Surprise
 for Race Semantics Users:</b> Following from the above, it could be surprising for developers when they realize that the inherent input ordering of
</span><span style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;background-color:rgb(255,255,255)"><code>mapConcurrent()</code></span><span style="background-color:rgb(255,255,255)"> means
 it's not optimized for these race scenarios. The expectation would be that </span>
<span style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;background-color:rgb(255,255,255)"><code>findFirst()</code></span><span style="background-color:rgb(255,255,255)"> returns
 as soon as <i>any</i> task completes, but ordering can delay this if an earlier task (in input order) is slower.</span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)"><br>
</span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)">This should be addressed above.<br>
<br>
><b>Ordering Assumption in Concurrency:</b> My experience is that ordering is not typically a default assumption when dealing with operations explicitly marked as "parallel" or "concurrent." For instance,
<code>Stream.forEach()</code> on a parallel stream does not guarantee encounter order, presumably for performance reasons – a similar trade-off to what's being discussed for
<code>mapConcurrent()</code>. Developers often consult documentation for ordering guarantees in concurrent contexts rather than assuming them.<br>
<br>
This should also be addressed above.<br>
<br>
><b>Expectation of "True" Concurrency:</b> When I see an API like <code>mapConcurrent(maxConcurrency, mapper)</code>, my mental model is that if
<code>maxConcurrency</code> permits, new tasks should be initiated as soon as a slot is free.<br>
<br>
</span></div>
<div style="font-size:12pt;color:rgb(0,0,0)">
<span style="background-color:rgb(255,255,255)">This is interesting, because this is how mapConcurrent used to work. It only placed the limit of
<b>concurrent work in progress</b> and not <b>work not yet possible to propagate downstream</b>. This was changed, because a delayed initial (in encounter order) item may let subsequent (completed) work queue up indefinitely.<br>
<br>
So in conclusion, there's still room for a different take on "mapConcurrentReorder" (name of course left up to the reader), and the good news is that such a Gatherer can be implemented, evaluated, hardened, etc outside of the JDK—and potentially some day something
 like it ends up in the JDK. </span></div></div></div></div></blockquote><div><br></div><div><p>Your mention of a potential <code class="gmail-">mapConcurrentReorder()</code> also brings to mind a thought about API consistency with existing Stream conventions. We see patterns like <code class="gmail-">Stream.forEach()</code> (which for parallel streams doesn't guarantee encounter order, prioritizing performance) versus <code class="gmail-">Stream.forEachOrdered()</code> (which explicitly enforces it). If <code class="gmail-">mapConcurrent()</code> were to follow a similar naming convention, it might suggest that the base <code class="gmail-">mapConcurrent()</code> itself would be the version optimized for throughput (and thus potentially unordered by default), while a hypothetical <code class="gmail-">mapConcurrentOrdered()</code> would be the variant explicitly providing the strict ordering guarantee. This is an observation on how naming might align with established JDK patterns to intuitively guide user expectations about the default behavior.</p><p>This naturally leads to the inherent challenge in designing such an API. It seems we're trying to balance three desirable, but sometimes conflicting, goals:</p><ol><li><strong>Strict Encounter Ordering:</strong> Results are emitted in the same order as the input elements.</li><li><strong>Bounded Memory Buffering:</strong> Avoid out-of-memory errors by not letting completed but un-emitted results queue up indefinitely.</li><li><strong>Optimized (True) Concurrency:</strong> If <code class="gmail-">maxConcurrency</code> is set (e.g., to <code class="gmail-">N</code>), the system strives to have <code class="gmail-">N</code> tasks actively running whenever there are pending input elements and available concurrency slots, rather than being stalled by a slow-to-complete but earlier-in-sequence task.</li></ol><p>It appears that achieving all three simultaneously is not possible, and a compromise must be made.</p><p>From my perspective:</p><ul><li>Goal #2 (Bounded Memory) is non-negotiable; OOM situations are generally unacceptable.</li><li>Goal #3 (Optimized Concurrency) feels fundamental to an API named <code class="gmail-">mapConcurrent()</code>. Users will likely expect it to maximize the concurrent execution of tasks up to the specified limit. Deviations from this, often necessitated by strict adherence to Goal #1, can lead to surprises.</li><li>Goal #1 (Strict Ordering), while a "nice-to-have" and sometimes beneficial, might not always align with common developer intuition for operations explicitly labeled "concurrent," especially if it compromises true concurrency. As discussed, ordering can often be reintroduced by the caller if specifically needed.</li></ul><p>The current implementation understandably prioritizes #1 (Ordering) and #2 (Bounded Memory). However, this prioritization can lead to situations where #3 (Optimized Concurrency) is not fully realized, which can be counter-intuitive.</p><p>I've already mentioned the race scenario. Consider another example where this becomes particularly evident. Imagine a scenario with a long-running task (e.g., for periodic monitoring) combined with a stream of other "real" tasks:</p><span class="gmail-ng-tns-c3281984513-82 gmail-ng-star-inserted"><div class="gmail-code-block gmail-ng-tns-c3281984513-82 gmail-ng-animate-disabled gmail-ng-trigger gmail-ng-trigger-codeBlockRevealAnimation"><div class="gmail-code-block-decoration gmail-header-formatted gmail-gds-title-s gmail-ng-tns-c3281984513-82 gmail-ng-star-inserted"><span class="gmail-ng-tns-c3281984513-82">Java</span><div class="gmail-buttons gmail-ng-tns-c3281984513-82 gmail-ng-star-inserted"><button aria-label="Copy code" class="gmail-mdc-icon-button gmail-mat-mdc-icon-button gmail-mat-mdc-button-base gmail-mat-mdc-tooltip-trigger gmail-copy-button gmail-ng-tns-c3281984513-82 gmail-mat-unthemed gmail-_mat-animation-noopable gmail-ng-star-inserted"><span class="gmail-mat-mdc-button-persistent-ripple gmail-mdc-icon-button__ripple"></span><span role="img" class="gmail-mat-icon gmail-notranslate gmail-google-symbols gmail-mat-ligature-font gmail-mat-icon-no-color" aria-hidden="true"></span><span class="gmail-mat-focus-indicator"></span><span class="gmail-mat-mdc-button-touch-target"></span></button></div></div><div class="gmail-formatted-code-block-internal-container gmail-ng-tns-c3281984513-82"><div class="gmail-animated-opacity gmail-ng-tns-c3281984513-82"><pre class="gmail-ng-tns-c3281984513-82"><code role="text" class="gmail-code-container gmail-formatted gmail-ng-tns-c3281984513-82"><span class="gmail-hljs-comment">// Main tasks</span>
List<Callable<Result>> realTasks = ... ;

<span class="gmail-hljs-comment">// A long-running monitoring task</span>
Callable<Void> longRunningMonitoringTask = () -> {
    <span class="gmail-hljs-keyword">while</span> (!allRealTasksSeemDone()) { <span class="gmail-hljs-comment">// Simplified condition</span>
        System.out.println(<span class="gmail-hljs-string">"Monitoring..."</span>);
        Thread.sleep(<span class="gmail-hljs-number">5000</span>);
    }
    <span class="gmail-hljs-keyword">return</span> <span class="gmail-hljs-keyword">null</span>;
};

Stream<Callable<?>> allTasks = Stream.concat(
    Stream.of(longRunningMonitoringTask),
    realTasks.stream().map(task -> (Callable<?>) task)
);

allTasks
    .gather(Gatherers.mapConcurrent(MAX_CONCURRENCY, callable -> callable.call()))
    .forEach(result -> { <span class="gmail-hljs-comment">/* output results */</span> });
</code></pre></div></div></div></span><p>The <code class="gmail-">longRunningMonitoringTask</code> would usually be the first element, with the current strictly ordered behavior, it would occupy one of the <code class="gmail-">MAX_CONCURRENCY</code> slots. and as soon as MAX_CONCURRENCY tasks are executed, completed or not, all subsequent <code class="gmail-">realTasks</code> (beyond the first one) would be starved, unable to even start until the <code class="gmail-">longRunningMonitoringTask</code> completes—which is <em class="gmail-">never</em>. This creates a deadlock or significant processing delay that would likely surprise a developer expecting tasks to proceed concurrently up to the <code class="gmail-">maxConcurrency</code> limit. An implementation more aligned with the "base name implies throughput" idea (as per the <code class="gmail-">forEach</code> analogy) would likely handle this more gracefully by letting tasks run truly concurrently without an implicit ordering dependency.</p><p>This reinforces my belief that an alternative gatherer, or a default behavior for <code class="gmail-">mapConcurrent()</code> that prioritizes concurrency (as the name <code class="gmail-">mapConcurrent</code> might suggest to many, akin to <code class="gmail-">forEach</code>), could be very valuable. I understand this might be something that evolves outside the JDK initially, and I appreciate you highlighting that path.</p><p>Thanks again for the continued discussion and the transparency about the design choices.</p><p>Best regards,</p></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="msg1559302929934323246"><div dir="ltr"><div id="m_1559302929934323246Signature">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,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)">
Cheers,<br>
√</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</div>
</div>
<div id="m_1559302929934323246appendonsend"></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 style="display:inline-block;width:98%">
<div id="m_1559302929934323246divRplyFwdMsg">
<div style="direction:ltr;font-family:Calibri,sans-serif;font-size:11pt;color:rgb(0,0,0)">
<b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Wednesday, 4 June 2025 16:20<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" target="_blank">viktor.klang@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Re: [External] : Re: Should mapConcurrent() respect time order instead of input order?</div>
<div style="direction:ltr"> </div>
</div>
<p style="direction:ltr">Hi Viktor,</p>
<p style="direction:ltr">Thank you for sharing that the general feedback on <code>
mapConcurrent()</code> has been positive and for the insights into the ongoing enhancements, especially around interruption handling and work-in-progress tracking.</p>
<p style="direction:ltr">To clarify my own position, I am also extremely enthusiastic about the
<code>mapConcurrent()</code> API overall. It offers an elegant and straightforward way to manage homogenous, I/O-intensive concurrent tasks within a structured concurrency model, which is a significant improvement and a much-needed addition. My feedback on
 ordering is aimed at maximizing its potential.</p>
<p style="direction:ltr">I'd like to elaborate on a few specific scenarios and expectations that inform my perspective on the ordering:</p>
<ol start="1" style="direction:ltr">
<li>
<p style="direction:ltr"><b>Temptation for Race Semantics:</b> The beauty of
<code>mapConcurrent()</code> integrating with the Stream API means developers will naturally be drawn to use it for race-like scenarios. Operations like
<code>findFirst()</code> or <code>limit(N)</code> to get the first few completed results are very intuitive combinations. For example:</p>
<div style="direction:ltr">Java</div>
<div style="direction:ltr"><button style="color:inherit">
</button></div>
<pre><div style="direction:ltr"><code>// Hypothetical use case: find the fastest responding service
Optional<Result> fastestResult = serviceUrls.stream()
    .gather(Gatherers.mapConcurrent(MAX_CONCURRENCY, url -> fetch(url)))
    .findFirst();
</code></div></pre>
</li><li>
<p style="direction:ltr"><b>Surprise for Race Semantics Users:</b> Following from the above, it could be surprising for developers when they realize that the inherent input ordering of
<code>mapConcurrent()</code> means it's not optimized for these race scenarios. The expectation would be that
<code>findFirst()</code> returns as soon as <i>any</i> task completes, but ordering can delay this if an earlier task (in input order) is slower.</p>
</li><li>
<p style="direction:ltr"><b>Ordering Assumption in Concurrency:</b> My experience is that ordering is not typically a default assumption when dealing with operations explicitly marked as "parallel" or "concurrent." For instance,
<code>Stream.forEach()</code> on a parallel stream does not guarantee encounter order, presumably for performance reasons – a similar trade-off to what's being discussed for
<code>mapConcurrent()</code>. Developers often consult documentation for ordering guarantees in concurrent contexts rather than assuming them.</p>
</li><li>
<p style="direction:ltr"><b>Expectation of "True" Concurrency:</b> When I see an API like
<code>mapConcurrent(maxConcurrency, mapper)</code>, my mental model is that if <code>
maxConcurrency</code> permits, new tasks should be initiated as soon as a slot is free. For example, with
<code>maxConcurrency=2</code>:</p>
</li><ul style="direction:ltr">
<li style="direction:ltr">Task 1 starts.</li><li style="direction:ltr">Task 2 starts.</li><li style="direction:ltr">If Task 2 finishes while Task 1 is still running, I would expect Task 3 to run concurrently alongside task 1, because the max concurrency is 2, not 1. The current ordered behavior, where Task 3 might have to wait for Task 1 to complete
 before its result can be processed (even if Task 3 itself could have started and finished), can feel a bit counterintuitive to the notion of maximizing concurrency up to the specified limit. It almost feels like not a "max concurrency", but "max buffer size".</li></ul>
</ol>
<p style="direction:ltr">These points are offered to highlight potential areas where the current default could lead to subtle surprises or suboptimal performance for useful concurrent patterns.</p>
<p style="direction:ltr">Thanks again for the open discussion and for your work on these valuable additions to the JDK.</p>
<p style="direction:ltr">Best regards,</p>
<div><br>
</div>
<div style="direction:ltr">On Tue, Jun 3, 2025 at 2:13 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="m_1559302929934323246OWA4e4e68a8-1e4d-ff8f-127b-3dcb25021590" target="_blank">viktor.klang@oracle.com</a>> wrote:</div>
<blockquote style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left:1px solid rgb(204,204,204)">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
The general feedback received thus far has been primarily positive. There have been a few behavior-related enhancements over the previews to better handle interruption (there's still room to improve there, as per our concurrent conversation) as well as some
 improvements to work-in-progress tracking.<br>
<br>
It will be interesting to see which Gatherer-based operations will be devised by Java developers in the future.</div>
<div id="m_1559302929934323246x_m_7394624936452812241Signature">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="m_1559302929934323246x_m_7394624936452812241appendonsend"></div>
<hr style="direction:ltr;display:inline-block;width:98%">
<div id="m_1559302929934323246x_m_7394624936452812241divRplyFwdMsg">
<div style="direction:ltr;font-family:Calibri,sans-serif;font-size:11pt;color:rgb(0,0,0)">
<b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" id="m_1559302929934323246OWA023a7fe7-a7d0-faae-0ad0-cbfe95c5d21c" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Monday, 2 June 2025 18:54<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="m_1559302929934323246OWAa3334c19-b6db-9fe0-e221-f43aba40c27b" target="_blank">viktor.klang@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" id="m_1559302929934323246OWAf325e363-2c53-94e9-e2a2-9d250702aa11" target="_blank">
core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" id="m_1559302929934323246OWAadf28b56-6076-794e-35ab-e77b48548c70" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Re: [External] : Re: Should mapConcurrent() respect time order instead of input order?</div>
<div style="direction:ltr"> </div>
</div>
<p style="direction:ltr">Hi Viktor,</p>
<p style="direction:ltr">Thanks for your reply and for sharing your experience regarding user preferences. I appreciate that perspective.</p>
<p style="direction:ltr">You're right, if an unordered version of <code>mapConcurrent</code> proves to be widely beneficial and is implemented and adopted by the community, it could certainly make a strong case for future inclusion in the JDK.</p>
<p style="direction:ltr">I wanted to clarify a nuance regarding user preference that I might not have articulated clearly before. If the question is simply "ordered or unordered?", in isolation, I can see why many, myself included, might lean towards "ordered"
 as a general preference.</p>
<p style="direction:ltr">However, the decision becomes more complex when the associated trade-offs are considered. If the question were phrased more like, "Do you prefer an ordered
<code>mapConcurrent</code> by default, even if it entails potential performance overhead and limitations for certain use cases like
<code>race()</code> operations, versus an unordered version that offers higher throughput and broader applicability in such scenarios?" my (and perhaps others') answer might differ. The perceived cost versus benefit of ordering changes significantly when these
 factors are explicit.</p>
<p style="direction:ltr">My initial suggestion stemmed from the belief that the performance and flexibility gains of an unordered approach for I/O-bound tasks would, in many practical situations, outweigh the convenience of default ordering, especially since
 ordering can be reintroduced relatively easily, and explicitly, when needed.</p>
<p style="direction:ltr">Thanks again for the discussion.</p>
<p style="direction:ltr">Best regards,</p>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">On Mon, Jun 2, 2025 at 8:51 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="m_1559302929934323246OWA92f93819-8db8-4db0-bd6b-3d2b386335d2" target="_blank">viktor.klang@oracle.com</a>> wrote:</div>
<blockquote style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left:1px solid rgb(204,204,204)">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
>My perspective is that strict adherence to input order for <code>mapConcurrent()</code> might not be the most common or beneficial default behavior for users.</div>
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158Signature">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
If there is indeed a <b>majority</b> who would benefit from an unordered version of mapConcurrent (my experience is that the majority prefer ordered) then, since it is possible to implement such a Gatherer outside of the JDK, this is something which will be
 constructed, widely used, and someone will then propose to add something similar to the JDK.</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
>While re-implementing the gatherer is a possibility, the existing implementation is non-trivial, and creating a custom, robust alternative represents a significant undertaking.</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
The existing version needs to maintain order, which adds to the complexity of the implementation. Implementing an unordered version would likely look different.</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
I'd definitely encourage taking the opportunity to attempt to implement it.</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158appendonsend"></div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<hr style="direction:ltr;display:inline-block;width:98%">
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158divRplyFwdMsg">
<div style="direction:ltr;font-family:Calibri,sans-serif;font-size:11pt;color:rgb(0,0,0)">
<b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" id="m_1559302929934323246OWAd4fad2d8-9c02-e46a-f01d-9cfe620d5b38" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Monday, 2 June 2025 17:05<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="m_1559302929934323246OWAfad1eed2-d549-8bea-5b8a-14715b5b423c" target="_blank">viktor.klang@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" id="m_1559302929934323246OWAa304f899-e110-9460-5fbc-a66410663ed6" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" id="m_1559302929934323246OWA9b4d8e81-d1bf-bde6-e02c-1420d08ac27a" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Re: [External] : Re: Should mapConcurrent() respect time order instead of input order?</div>
<div style="direction:ltr"> </div>
</div>
<p style="direction:ltr">Thank you for your response and for considering my feedback on the
<code>mapConcurrent()</code> gatherer. I understand and respect that the final decision rests with the JDK maintainers.</p>
<p style="direction:ltr">I would like to offer a couple of further points for consideration. My perspective is that strict adherence to input order for
<code>mapConcurrent()</code> might not be the most common or beneficial default behavior for users. I'd be very interested to see any research or data that suggests otherwise, as that would certainly inform my understanding.</p>
<p style="direction:ltr">From my experience, a more common need is for higher throughput in I/O-intensive operations. The ability to support use cases like
<code>race()</code>—where the first successfully completed operation determines the outcome—also seems like a valuable capability that is currently infeasible due to the ordering constraint.</p>
<p style="direction:ltr">As I see it, if a developer specifically requires the input order to be preserved, this can be achieved with relative ease by applying a subsequent sorting operation. For instance:</p>
<pre><div style="direction:ltr"><code>.gather(mapConcurrent(...))
.sorted(Comparator.comparing(Result::getInputSequenceId))
</code></div></pre>
<p style="direction:ltr">The primary challenge in these scenarios is typically the efficient fan-out and execution of concurrent tasks, not the subsequent sorting of results.</p>
<p style="direction:ltr">Conversely, as you've noted, there isn't a straightforward way to modify the current default ordered behavior to achieve the higher throughput or
<code>race()</code> semantics that an unordered approach would naturally provide.</p>
<p style="direction:ltr">While re-implementing the gatherer is a possibility, the existing implementation is non-trivial, and creating a custom, robust alternative represents a significant undertaking. My hope was that an unordered option could be a valuable
 addition to the standard library, benefiting a wider range of developers.</p>
<p style="direction:ltr">Thank you again for your time and consideration.</p>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">On Mon, Jun 2, 2025 at 7:48 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="m_1559302929934323246OWAcaa12256-7255-9e21-a03a-4704c8d37d9c" target="_blank">viktor.klang@oracle.com</a>> wrote:</div>
<blockquote style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left:1px solid rgb(204,204,204)">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
>Even if it by default preserves input order, when I explicitly called stream.unordered(), could mapConcurrent() respect that and in return achieve higher throughput with support for race?</div>
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158x_m_4397928128062799969Signature">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
The Gatherer doesn't know whether the Stream is unordered or ordered. The operation should be semantically equivalent anyway.</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158x_m_4397928128062799969appendonsend">
</div>
<hr style="direction:ltr;display:inline-block;width:98%">
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158x_m_4397928128062799969divRplyFwdMsg">
<div style="direction:ltr;font-family:Calibri,sans-serif;font-size:11pt;color:rgb(0,0,0)">
<b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" id="m_1559302929934323246OWA43500d2f-01f6-35cb-75bb-cef8f47e2745" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Monday, 2 June 2025 16:29<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="m_1559302929934323246OWA5f47910a-d81b-0fbd-9b6d-63ec26b0e708" target="_blank">viktor.klang@oracle.com</a>>;
<a href="mailto:core-libs-dev@openjdk.org" id="m_1559302929934323246OWAc7dd5521-a0e8-11b0-c0ca-c440c303be5f" target="_blank">
core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" id="m_1559302929934323246OWAd4147816-0e91-1605-0a9b-5e111218a8cc" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> [External] : Re: Should mapConcurrent() respect time order instead of input order?</div>
<div style="direction:ltr"> </div>
</div>
<div style="direction:ltr">Sorry. Forgot to copy to the mailing list.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">On Mon, Jun 2, 2025 at 7:27 AM Jige Yu <<a href="mailto:yujige@gmail.com" id="m_1559302929934323246OWAe73afa4e-3d6a-933a-a958-9618a65b8e3a" target="_blank">yujige@gmail.com</a>> wrote:</div>
<blockquote style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left:1px solid rgb(204,204,204)">
<div style="direction:ltr">Thanks Viktor!</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">I was thinking from my own experience that I wouldn't have automatically assumed that a concurrent fanout library would by default preserve input order. </div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">And I think wanting high throughput with real-life utilities like race would be more commonly useful.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">But I could be wrong. </div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Regardless, mapConcurrent() can do both, no? </div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Even if it by default preserves input order, when I explicitly called stream.unordered(), could mapConcurrent() respect that and in return achieve higher throughput with support for race?</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">On Mon, Jun 2, 2025 at 2:33 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="m_1559302929934323246OWA730565ba-cf98-d497-a75b-8d2d2eb6a94a" target="_blank">viktor.klang@oracle.com</a>> wrote:</div>
<blockquote style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left:1px solid rgb(204,204,204)">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Hi!</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
In a similar vein to the built-in Collectors,</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
the built-in Gatherers provide solutions to common stream-related problems, but also, they also serve as "inspiration" for developers for what is possible to implement using Gatherers.</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
If someone, for performance reasons, and with a use-case which does not require encounter-order, want to take advantage of that combination of circumstances, it is definitely possible to implement your own Gatherer which has that behavior.</div>
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158x_m_4397928128062799969x_m_-1609416137456101297m_-5453718620750210517Signature">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158x_m_4397928128062799969x_m_-1609416137456101297m_-5453718620750210517appendonsend">
</div>
<hr style="direction:ltr;display:inline-block;width:98%">
<div id="m_1559302929934323246x_m_7394624936452812241x_m_-6626157483800923158x_m_4397928128062799969x_m_-1609416137456101297m_-5453718620750210517divRplyFwdMsg">
<div style="direction:ltr;font-family:Calibri,sans-serif;font-size:11pt;color:rgb(0,0,0)">
<b>From:</b> core-libs-dev <<a href="mailto:core-libs-dev-retn@openjdk.org" id="m_1559302929934323246OWA32d7264b-3ae8-2217-0edf-bab4645c3c46" target="_blank">core-libs-dev-retn@openjdk.org</a>> on behalf of Jige Yu <<a href="mailto:yujige@gmail.com" id="m_1559302929934323246OWA5f9351f7-33d2-7b01-91f5-916e155d0116" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Sunday, 1 June 2025 21:08<br>
<b>To:</b> <a href="mailto:core-libs-dev@openjdk.org" id="m_1559302929934323246OWAf218dbbe-0556-5dc7-8db6-81a81b7cf428" target="_blank">
core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" id="m_1559302929934323246OWA6ebf0196-69c7-0208-2d34-9c78f2de8acd" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Should mapConcurrent() respect time order instead of input order?</div>
<div style="direction:ltr"> </div>
</div>
<div style="direction:ltr">It seems like for most people, input order isn't that important for concurrent work, and concurrent results being in non-deterministic order is often expected.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">If mapConcurrent() just respect output encounter order:</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">It'll be able to achieve <b>higher throughput</b> if an early task is slow, For example, with concurrency=2, and if the first task takes 10 minutes to run, mapConcurrent() would only be able to process 2 tasks within the first 10
 minutes; whereas with encounter order, the first task being slow doesn't block the 3rd - 100th elements from being processed and output.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">mapConcurrent() can be used to implement useful concurrent semantics, for example to
<b>support race</b> semantics. Imagine if I need to send request to 10 candidate backends and take whichever that succeeds first, I'd be able to do:</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">backends.stream()</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">    .gather(mapConcurrent(</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">        backend -> {</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">          try {</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">            return backend.fetchOrder();</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">           } catch (RpcException e) {</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">             return null; // failed to fetch but not fatal</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">           }</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">        })</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">        .filter(Objects::notNull)</div>
<div style="direction:ltr;margin-right:0px;margin-left:40px">        .findFirst(); // first success then cancel the rest</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Cheers,</div>
<div style="direction:ltr"><br>
</div>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</div>

</div></blockquote></div></div>