To combine multiple CompletableFuture objects in Java, you can use the following approaches, depending on your specific use case:
1. Combine Two Futures
If you have two CompletableFuture instances and need to combine their results, use the thenCombine method. It lets you specify how to merge the results of both futures.
Example:
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Task1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Task2");
// Combine their results
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
return result1 + " & " + result2; // Merge both results
});
combinedFuture.thenAccept(result -> System.out.println("Combined Result: " + result));
Output:
Combined Result: Task1 & Task2
2. Wait for All Futures to Complete
If you want to wait for multiple CompletableFuture tasks to complete (without necessarily combining their results immediately), you can use the allOf method. This is useful when you want to ensure that all tasks are completed before proceeding further.
Example:
CompletableFuture<Void> allTasks = CompletableFuture.allOf(
CompletableFuture.runAsync(() -> System.out.println("Task 1 completed")),
CompletableFuture.runAsync(() -> System.out.println("Task 2 completed")),
CompletableFuture.runAsync(() -> System.out.println("Task 3 completed"))
);
// Wait for all tasks to complete
allTasks.join();
System.out.println("All tasks completed.");
3. Combine Results of Multiple Futures
To combine the individual results of a list (or array) of CompletableFuture objects, you would use allOf in conjunction with further processing.
For example:
- Create a list/array of
CompletableFuture. - Use
CompletableFuture.allOf()to wait for all of them. - Extract and combine results using
join.
Example:
List<CompletableFuture<String>> futures = Arrays.asList(
CompletableFuture.supplyAsync(() -> "Result1"),
CompletableFuture.supplyAsync(() -> "Result2"),
CompletableFuture.supplyAsync(() -> "Result3")
);
CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
// Gather results once all are completed
CompletableFuture<List<String>> resultFuture = allOf.thenApply(v ->
futures.stream()
.map(CompletableFuture::join) // Join and collect results
.collect(Collectors.toList())
);
resultFuture.thenAccept(results -> System.out.println("Results: " + results));
Output:
Results: [Result1, Result2, Result3]
4. Wait for the First to Complete
If you are waiting for the first CompletableFuture to complete instead of all, use anyOf. It is useful when results from the first completed task suffice.
Example:
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(
CompletableFuture.supplyAsync(() -> "First Result"),
CompletableFuture.supplyAsync(() -> "Second Result"),
CompletableFuture.supplyAsync(() -> "Third Result")
);
anyOf.thenAccept(result -> System.out.println("First completed task result: " + result));
Comparison of APIs for Combining Futures:
| Method | Purpose |
|---|---|
thenCombine |
Combines two futures’ results into one. |
thenCompose |
Chains dependent tasks (where one task’s result is input for the next). |
allOf |
Waits for all futures in a list/array to complete but does not return their results. |
anyOf |
Waits for the first future from a list/array to complete and returns its result. |
By selecting the appropriate method (thenCombine, allOf, anyOf, or others), you can efficiently handle multiple asynchronous computations in Java with CompletableFuture.
