92

Java 8 has a function CompletableFuture.allOf(CompletableFuture<?>...cfs) that returns a CompletableFuture that is completed when all the given futures complete.

However, I almost always am not dealing with an array of CompletableFutures, but instead have a List<CompletableFuture>. Of course, I can use the toArray() method, but this ends up being a bit of a pain to have to constantly convert back and forth between arrays and lists.

It would be really nice if there were a slick way get a CompletableFuture<List<T>> in exchange for a List<CompletableFuture<T>>, instead of constantly having to throw in an intermediary array creation. Does anyone know a way to do this in Java 8?

therealrootuser
  • 10,215
  • 7
  • 31
  • 46

1 Answers1

82

Unfortunately, to my knowledge CompletableFuture does not support collections.

You could do something like this to make the code a bit cleaner, but it essentially does the same thing

public <T> CompletableFuture<List<T>> allOf(List<CompletableFuture<T>> futuresList) {
    CompletableFuture<Void> allFuturesResult =
    CompletableFuture.allOf(futuresList.toArray(new CompletableFuture[futuresList.size()]));
    return allFuturesResult.thenApply(v ->
            futuresList.stream().
                    map(future -> future.join()).
                    collect(Collectors.<T>toList())
    );
}

Found this very informative : http://www.nurkiewicz.com/2013/05/java-8-completablefuture-in-action.html

Deepak
  • 1,347
  • 7
  • 20
  • 31
    Use `CompletableFuture.allOf(futuresList.toArray(new CompletableFuture[futuresList.size()]))` since CompletableFuture.allOf() takes in an array of `CompletableFuture`. – wz366 Aug 22 '17 at 21:30
  • 1
    @wz366 this works but I'm getting a warning from IntelliJ on `new CompletableFuture[futuresList.size()]` saying `Array of type Object[]` expected – Kousha Oct 23 '17 at 18:05
  • 21
    I don't understand the benefit of using `allOf` in combination with `join` method. You could directly write `return futuresList.stream().map(CompletableFuture::join).collect(Collectors.toList())` – Olivier Boissé May 09 '18 at 22:14
  • 1
    I also found this tutorial very helpful and best explanation I've found so far on CompletableFuture: https://www.callicoder.com/java-8-completablefuture-tutorial/ – GameSalutes Oct 10 '18 at 13:37
  • 1
    @OlivierBoissé sometime we don't want to block the thread and just simply what to wrap the list of futures into a single returnable future for other logic to consume – Sitian Liu May 09 '19 at 19:07
  • 15
    @OlivierBoissé it's about exceptions. If one of your futures completed with exception - your code will not wait for completion of all futures. While `allOf` will work as expected. – turbanoff Jul 12 '19 at 12:29
  • 24
    @OlivierBoissé when you write `return futuresList.stream().map(CompletableFuture::join).collect(Collectors.toList());` you are waiting right at this point for completion of all futures. In contrast, `return CompletableFuture.allOf( futuresList.toArray(new CompletableFuture>[0])).thenApply(v -> futuresList.stream() .map(future -> future.join()) .collect(Collectors.toList()) );` does not wait for any future but returns a new future which will get completed with the result list once all futures are completed. – Holger Nov 29 '19 at 14:09
  • final List futures= .... CompletableFuture.allOf(futures.stream().toArray(CompletableFuture[]::new)).join(); – Janitha Madushan Mar 26 '20 at 06:30
  • Just to clear up some possible confusion on that inner `future.join()`: _"...Since we’re calling future.join() after all the futures are complete, we’re not blocking anywhere."_ Meaning, we're just getting the result of already completed future. Taken from [callicoder.com/java-8-completablefuture-tutorial](https://www.callicoder.com/java-8-completablefuture-tutorial/) – ElectroBuddha Mar 28 '20 at 10:38
  • 5
    Use `futuresList.toArray(new CompletableFuture[0])` instead of `futuresList.toArray(new CompletableFuture[futuresList.size()])` on HotSpot 8. (https://stackoverflow.com/questions/174093/toarraynew-myclass0-or-toarraynew-myclassmylist-size) – ET-CS May 21 '20 at 05:42