code: @Deprecated
      public static <V> CompletableFuture<List<V>> allAsList(List<CompletableFuture<? extends V>> futures)
      {
          CompletableFuture<Void> allDoneFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
  
          // Eagerly propagate exceptions, rather than waiting for all the futures to complete first (default behavior)
          for (CompletableFuture<? extends V> future : futures) {
              future.whenComplete((v, throwable) -> {
                  if (throwable != null) {
                      allDoneFuture.completeExceptionally(throwable);
                  }
              });
          }
  
          return unmodifiableFuture(allDoneFuture.thenApply(v ->
                  futures.stream()
                          .map(CompletableFuture::join)
                          .collect(Collectors.<V>toList())));
      }
docs: Returns an unmodifiable future that is completed when all of the given
  futures complete. If any of the given futures complete exceptionally, then the
  returned future also does so immediately, with a CompletionException holding this exception
  as its cause. Otherwise, the results of the given futures are reflected in the
  returned future as a list of results matching the input order. If no futures are
  provided, returns a future completed with an empty list.