我们有一个异步方法:
public CompletableFuture<OlderCat> asyncGetOlderCat(String catName)给出一张猫的列表:
List<Cat> cats;我们想要创建一个批量操作,它将在cat名称和它的异步结果之间产生一个映射:
public CompletableFuture<Map<String, OlderCat>>我们还希望,如果从asyncGetOlderCat抛出异常,则不会将猫添加到地图中。
我们跟踪了this post和this one,并编写了以下代码:
List<Cat> cats = ...
Map<String, CompletableFuture<OlderCat>> completableFutures = cats
.stream()
.collect(Collectors.toMap(Cat::getName,
c -> asynceGetOlderCat(c.getName())
.exceptionally( ex -> /* null?? */ ))
));
CompletableFuture<Void> allFutures = CompletableFuture
.allOf(completableFutures.values().toArray(new CompletableFuture[completableFutures.size()]));
return allFutures.thenApply(future -> completableFutures.keySet().stream()
.map(CompletableFuture::join) ???
.collect(Collectors.toMap(????)));但目前还不清楚我们如何在allFutures中访问猫的名字,以及如何在OlderCat和catName之间进行匹配。
它能实现吗?
发布于 2019-06-06 20:12:27
你就快到了。您不需要将exceptionally()放在初始期货上,但应该在allOf()之后使用handle()而不是thenApply(),因为如果将来失败,allOf()也会失败。
在处理期货时,您可以从结果中筛选出失败的期货,并重新构建预期的映射:
Map<String, CompletableFuture<OlderCat>> completableFutures = cats
.stream()
.collect(toMap(Cat::getName, c -> asyncGetOlderCat(c.getName())));
CompletableFuture<Void> allFutures = CompletableFuture
.allOf(completableFutures.values().toArray(new CompletableFuture[0]));
return allFutures.handle((dummy, ex) ->
completableFutures.entrySet().stream()
.filter(entry -> !entry.getValue().isCompletedExceptionally())
.collect(toMap(Map.Entry::getKey, e -> e.getValue().join())));请注意,对join()的调用被保证是非阻塞的,因为thenApply()仅在所有期货完成后才会执行。
https://stackoverflow.com/questions/56475682
复制相似问题