advancedAdvanced & Design

How do you aggregate the results of N parallel CompletableFutures?

The standard approach is CompletableFuture.allOf(cf1, cf2, ..., cfN), which returns a CompletableFuture<Void> that completes only once every one of the given futures has completed. You then chain a step to collect the individual results, typically written as allOf(futures.toArray(...)).thenApply(v -> futures.stream().map(CompletableFuture::join).collect(toList())); calling join() inside that step is safe because allOf already guarantees every future is done by that point, so join() will never actually block. If you instead only care about whichever future finishes first, CompletableFuture.anyOf(cf1, cf2, cf3) returns a CompletableFuture<Object> that completes as soon as any one of them does, which you then cast to the expected type. As of Java 21, structured concurrency offers a cleaner alternative for this same pattern: StructuredTaskScope.open(Joiner.allSuccessfulOrThrow()) handles the fork-and-join bookkeeping for you without manual join() and allOf() calls.

Ready to master this question?

Generate a complete walkthrough — background, the full answer in plain language, a working code example explained line by line, a real-world scenario, common mistakes, and how this same question gets asked in different ways.

Sign in to generate a response

Next Step

Continue to How would you design a rate limiter that allows at most N requests per second?← Back to all Java Concurrency & Multithreading questions