Gibt es eine elegante Möglichkeit, den ersten Nicht-Null-Wert mehrerer Methoden-Returns in Java zu erhalten?

7
Du hast das schon oft selbst gesehen, davon bin ich sicher:

%Vor%

Wir haben verschiedene Quellen, in denen ein Objekt suchen kann. Als anschauliches Beispiel könnten wir uns vorstellen, dass wir zuerst prüfen, ob sich eine Benutzer-ID in einer Liste privilegierter Benutzer befindet. Wenn nicht, prüfen wir, ob sich die Benutzer-ID in der Liste der erlaubten Benutzer befindet. Sonst geben wir null zurück. (Es ist nicht das beste Beispiel, aber ich hoffe, es ist ein lebhaft genug.)

Guava bietet uns einige Helfer, die diesen Code weiter oben verschönern könnten:

%Vor%

Aber, wie die Erfahreneren unter uns schon gesehen haben, kann dies schlecht funktionieren, wenn die Nachschläge (d. h. queryXXXXSource(args) ) eine gewisse Zeit brauchen. Dies liegt daran, dass wir jetzt alle Quellen zuerst abfragen und dann die Ergebnisse an die Methode übergeben, die das erste dieser Ergebnisse findet, das nicht null ist.

Im Gegensatz zum ersten Beispiel, bei dem die nächste Quelle nur ausgewertet wird, wenn die erste nicht zurückkehrt, sieht diese zweite Lösung zunächst besser aus, könnte aber viel schlechter abschneiden.

Hier kommen wir zu meiner eigentlichen Frage und dazu, wo ich etwas davon vorschlage, ich hoffe, dass jemand bereits die Basis davon implementiert hat oder dass jemand eine sogar schlaue Lösung vorschlagen könnte.

Im Klartext: Hat jemand bereits ein solches defferedFirstNonNull (siehe unten) oder ähnliches implementiert? Gibt es eine einfache Plain-Java-Lösung, um dies mit dem neuen zu erreichen Stream Framework? Können Sie eine andere elegante Lösung vorschlagen, die das gleiche Ergebnis erzielt?

Regeln: Java 8 ist ebenso erlaubt wie aktive, gepflegte und bekannte Bibliotheken von Drittanbietern wie Google's Guava oder Apache's Commons Lang mit Apache License oder ähnliches (keine GPL!).

Die vorgeschlagene Lösung:

%Vor%

Also würde die Methode defferedFirstNonNull jeden Lambda-Ausdruck nach dem anderen auswerten und sobald das Prädikat ( x -> x != null ) wahr ist (dh wir fanden eine Übereinstimmung), würde die Methode das Ergebnis sofort zurückgeben und keine weitere Quelle abfragen .

PS: Ich weiß, dass die Ausdrücke args -> queryXXXXSource(args) auf queryXXXXSource verkürzt werden könnten. Aber das würde die vorgeschlagene Lösung schwerer lesbar machen, weil auf den ersten Blick nicht klar ist, was passieren wird.

    
cimnine 30.09.2014, 10:05
quelle

3 Antworten

7

Es hängt von einigen Faktoren ab, die Sie nicht definieren. Haben Sie einen festen, eher kleinen Satz von query…Source -Aktionen, wie in Ihrer Frage gezeigt, oder möchten Sie lieber eine flexiblere, erweiterbare Aktionsliste erstellen?

Im ersten Fall könnten Sie die Methoden query…Source so ändern, dass ein Optional<SomeObject> anstatt SomeObject oder null zurückgegeben wird. Wenn du deine Methoden änderst wie

%Vor%

Sie können sie auf diese Weise verketten:

%Vor%

Wenn Sie sie nicht ändern können oder sie null zurückgeben möchten, können Sie die Klasse Optional weiterhin verwenden:

%Vor%

Wenn Sie nach einer flexibleren Möglichkeit für eine größere Anzahl von möglichen Abfragen suchen, ist es unvermeidlich, sie in eine Art Liste oder einen Stream von Function s zu konvertieren. Eine mögliche Lösung ist:

%Vor%

Dies führt die gewünschte Operation durch, es wird jedoch die erforderliche Aktion jedes Mal erstellen, wenn Sie die Methode aufrufen. Wenn Sie diese Methode häufiger aufrufen möchten, können Sie eine Operation erstellen, die Sie erneut verwenden können:

%Vor%

Sie sehen also, es gibt mehr als einen Weg. Und es hängt von der eigentlichen Aufgabe ab, in welche Richtung es gehen soll. Manchmal ist sogar die einfache if -Sequenz geeignet.

    
Holger 30.09.2014, 17:26
quelle
10

Ja, es gibt:

%Vor%

Dies ist flexibler, da es eine Optional nicht null zurückgibt, falls eine nicht-null source gefunden wird.

Bearbeiten: Wenn Sie eine faule Auswertung wünschen, sollten Sie Supplier verwenden:

%Vor%     
m3th0dman 30.09.2014 10:08
quelle
5

Ich würde es so schreiben (du brauchst vielleicht keine Generika, aber warum nicht?):

%Vor%

Und Sie können es nennen mit:

%Vor%

(unter der Annahme, dass Ihre queryXXX -Methoden Instanzmethoden sind)

Die Methoden werden in der angegebenen Reihenfolge angewendet, bis ein Wert zurückgegeben wird, der dem Vergleichselement entspricht (im obigen Beispiel: gibt einen Nicht-Null-Wert zurück).

    
assylias 30.09.2014 10:32
quelle

Tags und Links