Normalement, avec un CompletableFuture, j'appelle thenApply ou une autre méthode pour faire quelque chose dès que le résultat est disponible. Cependant, j'ai maintenant une situation où je veux traiter des résultats jusqu'à ce que je reçoive un résultat positif, puis ignorer tous les autres résultats.En java, comment puis-je traiter CompletableFutures et obtenir le premier résultat désirable qui se termine?
Si je voulais juste prendre le premier résultat disponible, je pourrais utiliser CompletableFuture.anyOf (bien que je déteste avoir à convertir une liste en tableau pour appeler anyOf). Mais ce n'est pas ce que je veux. Je veux prendre le premier résultat et s'il n'a pas un résultat désirable, alors je veux traiter le deuxième résultat disponible et ainsi de suite jusqu'à ce que j'obtienne un résultat souhaitable.
Voici un exemple simple qui passe par tous les résultats et retourne la première valeur qu'il trouve qui est supérieure à 9. (Notez que ce n'est pas ma tâche réelle. Ceci est juste un exemple simple.)
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
for(CompletableFuture<Integer> result : results) {
Integer v = result.get();
if(v > 9)
return v;
}
return null;
}
Bien sûr, cet exemple passe par les résultats du début, pas en regardant les résultats à mesure qu'ils se terminent. Donc, voici celui qui accomplit ce que je veux, mais avec un code beaucoup plus compliqué.
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;
}
Y a-t-il une API où je peux simplement faire cela?
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;
}
Ou encore mieux:
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
return getFirstMatch(results, r -> {return r > 9;});
}