通常使用 CompletableFuture 我会在结果可用后立即调用 thenApply 或其他一些方法来执行某些操作。但是,我现在有一种情况,我想处理结果,直到收到肯定的结果,然后忽略所有进一步的结果。
如果我只想获取第一个可用结果,我可以使用 CompletableFuture.anyOf (尽管我讨厌将列表转换为数组只是为了调用 anyOf)。但这不是我想要的。我想获得第一个结果,如果它没有理想的结果,那么我想处理第二个可用的结果,依此类推,直到我得到理想的结果。
这是一个简单的示例,它遍历所有结果并返回它找到的第一个大于 9 的值。(请注意,这不是我真正的任务。这只是一个简单的示例。)
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
for(CompletableFuture<Integer> result : results) {
Integer v = result.get();
if(v > 9)
return v;
}
return null;
}
当然,该示例从一开始就检查结果,而不是在完成时查看结果。所以这是一个完成我想要的东西,但代码更复杂的一个。
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
AtomicInteger finalResult = new AtomicInteger();
CountDownLatch latch = new CountDownLatch(results.size());
for(CompletableFuture<Integer> result : results) {
result.whenComplete((v,e) -> {
if(e!=null) {
Logger.getLogger(getClass()).error("",e);
} else if(v > 9) {
finalResult.set(v);
while(latch.getCount() > 0)
latch.countDown();
return;
}
latch.countDown();
});
}
latch.await();
if(finalResult.get() > 9)
return finalResult.get();
return null;
}
有没有我可以做到这一点的api?
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
Iterator<Integer> resultIt = getResultsAsAvailable(results);
for(; resultIt.hasNext();) {
Integer v = resultIt.next();
if(v > 9)
return v;
}
return null;
}
甚至更好:
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
return getFirstMatch(results, r -> {return r > 9;});
}