преобразовать список завершаемых фьючерсов в одно завершаемое будущее списка

У меня есть список CompletableFuture экземпляров.

List<CompletableFuture<String>> listOfFutures;

Как преобразовать их в одно будущее, как это:

CompletableFuture<List<String>> futureOfList = convert(listOfFutures);

person Denis Kostousov    schedule 19.09.2015    source источник


Ответы (2)


Это монадическая операция последовательности. С помощью cyclops-monad-api (библиотека, которую я написал ) ты можешь написать

   AnyM<Stream<String>> futureStream = AnyMonads.sequence(
              AsAnyMList.completableFutureToAnyMList(futures));

   CompletableFuture<Stream<String>> futureOfList = futureStream.unwrap();

Когда вы вызываете терминальную операцию в потоке внутри futureOfList, например. чтобы преобразовать в список, он вызовет вызов join() для всех исходных фьючерсов, поэтому его следует использовать аналогично самому join().

    CompletableFuture<List<String>> completed = futureOfList.thenApply(
                  s->s.collect(Collectors.toList());

Чтобы написать свою версию специально для CompletableFuture, вы можете сделать что-то вроде этого

 CompletableFuture<Stream<String>> futureOfList = CompletableFuture.completedFuture(1)
           .thenCompose(one->listOfFutures.stream()
                                         .map(cf->cf.join()));

Затем присоединиться

CompletableFuture<List<String>> completed = futureOfList.thenApply(
                s->s.collect(Collectors.toList());

См. также этот вопрос и ответ для решения с использованием allOf (которое не будет блокировать дополнительные потоки ).

person John McClean    schedule 19.09.2015

Вы можете сделать это следующим образом:

public static <T> CompletableFuture<List<T>> convert(List<CompletableFuture<T>> futures) {
    return futures.stream().
            map(f -> f.thenApply(Stream::of)).
            reduce((a, b) -> a.thenCompose(xs -> b.thenApply(ys -> concat(xs, ys)))).
            map(f -> f.thenApply(s -> s.collect(toList()))).
            orElse(completedFuture(emptyList()));
}
person Yaroslav    schedule 22.02.2017