Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call completable future in a loop and combine all the results?

I am trying to achieve something like this. This is a made up example that expresses the intent.

I want all the completable futures to execute and combine all their results to one result and return that. So for the example below, the collection allResults should have the strings "one", "two", "three", 3 times each. I want them all to run in parallel and not serially.

Any pointers to what API on the completable future I could use to achieve this, would be very helpful.

public class Main {


    public static void main(String[] args) {

        int x = 3;
        List<String> allResuts;

        for (int i = 0; i < x; i++) {

           //call getCompletableFutureResult() and combine all the results
        }

    }

    public static CompletableFuture<List<String>> getCompletableFutureResult() {

        return CompletableFuture.supplyAsync(() -> getResult());
    }

    private static List<String> getResult() {


        List<String> list = new ArrayList<>();
        list.add("one");
        list.add("two");
        list.add("three");

        return list;
    }


}
like image 813
developer747 Avatar asked Sep 19 '25 23:09

developer747


1 Answers

There is an issue with answer from Venkata Raju. Raju used get call on future which is a blocking call and kills the main purpose of coding in Async style. Always avoid doing get on futures.

There are tons of built in methods build around handling future values like thenApply, thenAccept, thenCompose, thenCombine etc.

CompletableFuture.allOf method is meant to be used when you have to deal with multiple futures.

It has this following signature

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)

Side note: CompletableFuture.anyOf can be used when you only care about the first future to complete. Use allOf when you need all futures to complete.

I would code your spec in following way using CompletableFuture.allOf.

public class DorjeeTest {


    public static CompletableFuture<List<String>> getCompetableFutureResult() {
        return CompletableFuture.supplyAsync(() -> getResult());
    }
    public static List<String> getResult() {
        return Lists.newArrayList("one", "two", "three");
    }

    public static void testFutures() {
        int x = 3;
        List<CompletableFuture<List<String>>> futureResultList = Lists.newArrayList();
        for (int i = 0; i < x; i++) {
            futureResultList.add(getCompetableFutureResult());
        }

        CompletableFuture[] futureResultArray = futureResultList.toArray(new CompletableFuture[futureResultList.size()]);

        CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(futureResultArray);

        CompletableFuture<List<List<String>>> finalResults = combinedFuture
                .thenApply(voidd ->
                        futureResultList.stream()
                                .map(future -> future.join())
                        .collect(Collectors.toList()));

        finalResults.thenAccept(result -> System.out.println(result));
    }


    public static void main(String[] args) {
        testFutures();
        System.out.println("put debug break point on this line...");

    }
}
like image 149
Dorjee Avatar answered Sep 22 '25 13:09

Dorjee