问题
Like in this hypothetical example of using of
:
List<CompletionStage<Long>> listOfFutureLongs = getFutureLongs(...)
CompletionStage<List<Long>> futureListOfLongs = CompletionStage.of(listOfFutureLongs)
回答1:
Strangely no.
There's CompletableFuture.allOf
for CompletableFuture
, which is kind of like what you want, but no similar function for CompletionStage
.
You can either use CompletionStage.toCompletableFuture
to get futures, or you can write your own.
Unfortunately, the inability to check a CompletionStage
to see if it's done already means that you can't do this quite as efficiently.
This code is in a not-yet-released (also not yet tested) open source project of mine. Feel free to use it:
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);
}
}
}
回答2:
Internet says, use completable future:
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()));
来源:https://stackoverflow.com/questions/56135121/is-there-a-converter-from-listcompletionstage-to-completionstagelist-in-java