I am late to the party but here are my 2 cents
I am writing here about these three methods—thenApply()
, thenCompose()
, and thenCombine()
.. They might seem similar initially, but they serve distinct purposes.
thenApply()
CompletableFuture
.CompletableFuture
with the transformed result.thenApplyAsync
).CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hi Buddy")
.thenApply(result -> result + " .How are you?");
future.thenAccept(System.out::println);
thenCompose()
CompletableFuture
instances into a single one.CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "hi")
.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " .. hows life???"));
future.thenAccept(System.out::println);
Here, thenCompose()
chains two asynchronous tasks. The second CompletableFuture
depends on the result of the first.
Why flatten? Without thenCompose()
, you'd end up with CompletableFuture<CompletableFuture<String>>
, which isn't useful.
thenCombine()
CompletableFuture
results when both are complete.CompletableFuture
with the combined result.CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 2);
CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + result2);
combinedFuture.thenAccept(System.out::println); // prints 3
Here, thenCombine()
takes the results of two independent tasks (future1
and future2
) and combines them into a single result (3
).
thenApply()
: Transform the result of a single CompletableFuture
.
Think: Synchronous transformation.
thenCompose()
: Chain dependent asynchronous tasks.
Think: Task B depends on the result of Task A.
thenCombine()
: Combine results of two independent CompletableFutures
.
Think: Running two tasks in parallel and merging their results.