在Java中是否存在从List <completionstage>到CompletionStage <list>的转换器?

时间:2019-05-14 16:49:53

标签: java future completable-future completion-stage

就像使用of的假设示例一样:

List<CompletionStage<Long>> listOfFutureLongs = getFutureLongs(...)
CompletionStage<List<Long>> futureListOfLongs = CompletionStage.of(listOfFutureLongs)

2 个答案:

答案 0 :(得分:1)

奇怪的是。

CompletableFuture.allOfCompletableFuture,有点像您想要的,但是CompletionStage没有类似的功能。

您可以使用CompletionStage.toCompletableFuture获取期货,也可以编写自己的期货。

不幸的是,无法检查CompletionStage来查看是否已完成,这意味着您不能这么高效地进行此操作。

此代码在我的一个尚未发布(也尚未测试)的开源项目中。随时使用它:

public static <T> CompletionStage<List<T>> list(List<CompletionStage<T>> list)
{
    if (list.size() <= 0)
    {
        return CompletableFuture.completedFuture(Collections.emptyList());
    }
    if (list.size() == 1)
    {
        return list.get(0).thenApply(Collections::singletonList);
    }
    final AtomicInteger waiters = new AtomicInteger(1);
    final List<T> ret = new ArrayList<>(list.size());
    final AtomicReference<Throwable> retErr = new AtomicReference<>();
    final CompletableFuture<List<T>> retFuture = new CompletableFuture<>();
    for (int i = 0; i < list.size(); ++i)
    {
        ret.add(null);
        final int pos = i;
        final CompletionStage<T> cs = list.get(i);
        if (cs == null)
        {
            continue;
        }
        waiters.incrementAndGet();
        cs.whenComplete((val, err) -> {
            if (err != null)
            {
                retErr.compareAndSet(null, err);
            }
            ret.set(pos, val);
            _doneListItem(waiters, retFuture, ret, retErr.get());
        });
    }
    _doneListItem(waiters, retFuture, ret, retErr.get());
    return retFuture;
}

private static <T> void _doneListItem(AtomicInteger waitCount, CompletableFuture<List<T>> ret, List<T> val, Throwable err)
{
    if (waitCount.decrementAndGet() == 0)
    {
        if (err != null)
        {
            ret.completeExceptionally(err);
        }
        else
        {
            ret.complete(val);
        }
    }
}

答案 1 :(得分:1)

互联网说,使用可实现的未来:

List<CompletionStage<Long>> futureLongs = getFutureLongs();
var arr = futureLongs.toArray(new CompletableFuture[futureLongs.size()]);
CompletionStage<List<Long>> result = CompletableFuture.allOf(arr)
  .thenApply(unused -> futureLongs.stream().map(f -> f.toCompletableFuture().join()).collect(Collectors.toList()));