/** Like {@link CompletableFuture#allOf} but returning the result of constituent futures. */ public static <T> CompletionStage<List<T>> allAsList( Collection<? extends CompletionStage<? extends T>> futures) { // CompletableFuture.allOf completes exceptionally if any of the futures do. // We have to gather the results separately. CompletionStage<Void> blockAndDiscard = CompletableFuture.allOf(futuresToCompletableFutures(futures)); return blockAndDiscard.thenApply( nothing -> futures .stream() .map(future -> future.toCompletableFuture().join()) .collect(Collectors.toList())); }
/** Like {@link #allAsList} but return a list . */ public static <T> CompletionStage<List<ExceptionOrResult<T>>> allAsListWithExceptions( Collection<? extends CompletionStage<? extends T>> futures) { // CompletableFuture.allOf completes exceptionally if any of the futures do. // We have to gather the results separately. CompletionStage<Void> blockAndDiscard = CompletableFuture.allOf(futuresToCompletableFutures(futures)) .whenComplete((ignoredValues, arbitraryException) -> {}); return blockAndDiscard.thenApply( nothing -> futures .stream() .map( future -> { // The limited scope of the exceptions wrapped allows CancellationException // to still be thrown. try { return ExceptionOrResult.<T>result(future.toCompletableFuture().join()); } catch (CompletionException exc) { return ExceptionOrResult.<T>exception(exc); } }) .collect(Collectors.toList())); }