Normalerweise würde ich mit einer CompleableFuture dann apply oder eine andere Methode aufrufen, etwas zu tun, sobald das Ergebnis verfügbar ist. Allerdings habe ich jetzt eine Situation, in der ich Ergebnisse verarbeiten möchte, bis ich ein positives Ergebnis erhalte und dann alle weiteren Ergebnisse ignoriere.In Java, wie verarbeite ich CompletableFutures und bekomme das erste erwünschte Ergebnis, das vervollständigt wird?
Wenn ich nur das erste verfügbare Ergebnis nehmen wollte, konnte ich CompletableFuture.anyOf verwenden (obwohl ich es hasse, eine Liste in ein Array konvertieren zu müssen, um anyOf aufzurufen). Aber das will ich nicht. Ich möchte das erste Ergebnis ziehen und wenn es kein wünschenswertes Ergebnis hat, dann möchte ich das zweite verfügbare Ergebnis bearbeiten, bis ich ein wünschenswertes Ergebnis erhalte.
Hier ist ein einfaches Beispiel, das alle Ergebnisse geht durch und gibt den ersten Wert, der es findet, die als 9 größer ist (Beachten Sie, dass dies nicht meine eigentliche Aufgabe ist. Dies ist nur ein einfaches Beispiel.)
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
for(CompletableFuture<Integer> result : results) {
Integer v = result.get();
if(v > 9)
return v;
}
return null;
}
Natürlich durchläuft dieses Beispiel die Ergebnisse von Anfang an, nicht indem man die Ergebnisse betrachtet, wenn sie vollständig sind. Also hier ist einer, der das erreicht, was ich will, aber mit viel komplizierterem Code.
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;
}
Gibt es eine API, wo ich das tun kann?
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;
}
Oder noch besser:
public Integer findFirstGt9(List<CompletableFuture<Integer>> results) {
return getFirstMatch(results, r -> {return r > 9;});
}