Martin GOYOT
Martin GOYOT

Reputation: 296

How to make a future dependent on two others in Java

I have a future that would ideally take two parameters coming from two other futures. For this I have .thenCombine(), the trick here is that the second future needs the result of the first one.

Let's say:

I would like to have something like:

CompletableFuture<Customer> customerFuture = CompletableFuture.supplyAsync(() -> findCustomer(123));
CompletableFuture<Shop> shopFuture         = CompletableFuture.supplyAsync((customer) ->getAllAccessibleShops(customer));
CompletableFuture<Route> routeFuture       = customerFuture.thenCombine(shopFuture, (cust, shop) -> findRoute(cust, shop));

Of course thenCombine() is not what I'm looking for and the code above looks dumb because I shouldn't need the customer afterwards, but this is only an example.

Is there a way to achieve this?

Upvotes: 2

Views: 3684

Answers (1)

Didier L
Didier L

Reputation: 20618

Your solution is correct, the only issue is in the declaration of shopFuture. You should use thenApply[Async]() so that it can access the result of the first one:

CompletableFuture<Customer> customerFuture = CompletableFuture.supplyAsync(() -> findCustomer(123));
CompletableFuture<Shop> shopFuture         = customerFuture.thenApply((customer) -> getAllAccessibleShops(customer));
CompletableFuture<Route> routeFuture       = customerFuture.thenCombine(shopFuture, (cust, shop) -> findRoute(cust, shop));

Note that the execution order remains sequential since shopFuture requires the result of customerFuture, and routeFuture requires the result of shopFuture. However if you have additional work to do with the Customer or the Shop, you could use additional thenApply[Async] calls to run them.

If you don't have anything to do with those results, you might want to group all the 3 calls into a single supplyAsync():

CompletableFuture<Route> customerFuture = CompletableFuture.supplyAsync(() -> {
   Customer customer = findCustomer(123));
   Shop shop = getAllAccessibleShops(customer));
   return findRoute(customer, shop)
});

See also CompletableFuture, supplyAsync() and thenApply() for the difference in behaviour between the two.

Upvotes: 3

Related Questions