У меня есть список CompletableFuture
экземпляров.
List<CompletableFuture<String>> listOfFutures;
Как преобразовать их в одно будущее, как это:
CompletableFuture<List<String>> futureOfList = convert(listOfFutures);
У меня есть список CompletableFuture
экземпляров.
List<CompletableFuture<String>> listOfFutures;
Как преобразовать их в одно будущее, как это:
CompletableFuture<List<String>> futureOfList = convert(listOfFutures);
Это монадическая операция последовательности. С помощью 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 (которое не будет блокировать дополнительные потоки ).
Вы можете сделать это следующим образом:
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()));
}