Обычно с 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;});
}