Java 8 CompletableFuture.allOf() с коллекцией или списком

В Java 8 есть функция CompletableFuture.allOf(CompletableFuture<?>...cfs), который возвращает CompletableFuture, который завершается, когда завершаются все заданные фьючерсы.

Однако я почти всегда имею дело не с массивом CompletableFuture, а с массивом List<CompletableFuture>. Конечно, я могу использовать метод toArray(), но в конечном итоге это немного утомительно, чтобы постоянно конвертировать туда и обратно между массивами и списками.

Было бы очень хорошо, если бы был простой способ получить CompletableFuture<List<T>> в обмен на List<CompletableFuture<T>> вместо того, чтобы постоянно создавать промежуточный массив. Кто-нибудь знает способ сделать это в Java 8?


person therealrootuser    schedule 05.03.2016    source источник


Ответы (1)


К сожалению, насколько мне известно, CompletableFuture не поддерживает коллекции.

Вы можете сделать что-то подобное, чтобы сделать код немного чище, но по сути это то же самое.

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())
    );
}

Нашел это очень информативно: http://www.nurkiewicz.com/2013/05/java-8-completablefuture-in-action.html

person Deepak    schedule 05.03.2016
comment
Используйте CompletableFuture.allOf(futuresList.toArray(new CompletableFuture[futuresList.size()])), так как CompletableFuture.allOf() принимает массив CompletableFuture. - person wz366; 23.08.2017
comment
@wz366 wz366 это работает, но я получаю предупреждение от IntelliJ на new CompletableFuture[futuresList.size()] о том, что ожидается Array of type Object[] - person Kousha; 23.10.2017
comment
Я не понимаю преимуществ использования allOf в сочетании с методом join. Вы можете напрямую написать return futuresList.stream().map(CompletableFuture::join).collect(Collectors.toList()) - person Olivier Boissé; 10.05.2018
comment
Я также нашел этот учебник очень полезным и лучшим объяснением, которое я нашел до сих пор на CompletableFuture: callicoder.com/java-8-completablefuture-tutorial - person GameSalutes; 10.10.2018
comment
@OlivierBoissé иногда мы не хотим блокировать поток и просто что бы обернуть список фьючерсов в одно возвращаемое будущее для использования другой логикой - person Sitian Liu; 09.05.2019
comment
@OlivierBoissé об исключениях. Если один из ваших фьючерсов завершился с исключением - ваш код не будет ждать завершения всех фьючерсов. Пока allOf будет работать как положено. - person turbanoff; 12.07.2019
comment
@OlivierBoissé, когда вы пишете return futuresList.stream().map(CompletableFuture::join).collect(Collectors.toList());, вы прямо сейчас ждете завершения всех фьючерсов. Напротив, return CompletableFuture.allOf( futuresList.toArray(new CompletableFuture<?>[0])).thenApply(v -> futuresList.stream() .map(future -> future.join()) .collect(Collectors.<T>toList()) ); не ждет никакого будущего, а возвращает новое будущее, которое будет завершено со списком результатов после завершения всех фьючерсов. - person Holger; 29.11.2019
comment
окончательный список‹CompletableFuture‹Module› futures= .... CompletableFuture.allOf(futures.stream().toArray(CompletableFuture[]::new)).join(); - person Janitha Madushan; 26.03.2020
comment
Просто чтобы прояснить возможную путаницу с этим внутренним future.join(): ...Поскольку мы вызываем future.join() после завершения всех фьючерсов, мы нигде не блокируемся. Это означает, что мы' re просто получение результата уже завершенного будущего. Взято с callicoder.com/java-8-completablefuture-tutorial - person ElectroBuddha; 28.03.2020
comment
Используйте futuresList.toArray(new CompletableFuture[0]) вместо futuresList.toArray(new CompletableFuture[futuresList.size()]) в HotSpot 8. (stackoverflow.com/questions/174093/) - person ET-CS; 21.05.2020