Ich habe den folgenden Code, der für mehrere Nullprüfungen etwas hässlich ist.
String s = null;
if (str1 != null) {
s = str1;
} else if (str2 != null) {
s = str2;
} else if (str3 != null) {
s = str3;
} else {
s = str4;
}
Also versuchte ich es mit Optional.ofNullable wie unten, aber es ist immer noch schwer zu verstehen, wenn jemand meinen Code liest. Was ist der beste Ansatz dafür in Java 8.
String s = Optional.ofNullable(str1)
.orElse(Optional.ofNullable(str2)
.orElse(Optional.ofNullable(str3)
.orElse(str4)));
In Java 9 können wir verwenden Optional.ofNullablemit ORAber gibt es in Java8 einen anderen Ansatz ?
Java9 or Syntax String s = Optional.ofNullable(str1) .or(() -> Optional.ofNullable(str2)) .or(() -> Optional.ofNullable(str3)) .orElse(str4); sieht nicht so gut aus wie die Stream.of Ich würde ja.
– Namann
21. Februar 2019 um 6:55 Uhr
Ich weiß, dass der Benutzer nach einer Java-8-spezifischen Lösung fragt, aber allgemein würde ich mitmachen StringUtils.firstNonBlank()
– Mohamed Anees A
21. Februar 2019 um 12:09 Uhr
Das Problem ist, dass Java 8/streams dafür nicht die beste Lösung ist. Dieser Code riecht wirklich so, als wäre ein Refactor in Ordnung, aber ohne mehr Kontext ist es wirklich schwer zu sagen. Für den Anfang – warum sind drei Objekte, die wahrscheinlich so eng miteinander verwandt sind, nicht bereits in einer Sammlung?
– Bill K
21. Februar 2019 um 17:49 Uhr
@MohamedAneesA hätte die beste Antwort (als Kommentar) gegeben, aber in diesem Fall nicht die Quelle von StringUtils angegeben. Wenn Sie diese auf jeden Fall als eine Reihe separater Zeichenfolgen haben MÜSSEN, ist die Codierung als Varg-Methode wie “firstNonBlank” ideal. Die Syntax darin ist ein Array, das eine einfache For-Each-Schleife mit einer Rückgabe beim Auffinden von a erstellt Nicht-Null-Wert trivial und offensichtlich. In diesem Fall sind Java-8-Streams ein attraktives Ärgernis. Sie verleiten Sie dazu, etwas zu inlinen und zu komplizieren, das eine einfache Methode/Schleife sein sollte.
– Bill K
21. Februar 2019 um 17:55 Uhr
stackoverflow.com/q/2768054/31782
– n0rd
21. Februar 2019 um 20:48 Uhr
Ravindra Ranwala
Du kannst es so machen:
String s = Stream.of(str1, str2, str3)
.filter(Objects::nonNull)
.findFirst()
.orElse(str4);
Dies. Denken Sie an das, was Sie brauchen, nicht an das, was Sie haben.
– Thorbjørn Ravn Andersen
21. Februar 2019 um 8:23 Uhr
Wie hoch ist der Geschwindigkeits-Overhead? Erstellen von Stream-Objekten, Aufrufen von 4 Methoden, Erstellen von temporären Arrays ({str1, str2, str3}) viel langsamer aussehen als ein Einheimischer if oder ?:, die die Java-Laufzeit optimieren kann. Gibt es eine Stream-spezifische Optimierung in javac und die Java-Laufzeit, die es so schnell macht wie ?:? Wenn nicht, empfehle ich diese Lösung nicht in leistungskritischem Code.
– Pkt
21. Februar 2019 um 9:58 Uhr
@pts das ist sehr wahrscheinlich langsamer als ?: Code und ich bin sicher, dass Sie es in leistungskritischem Code vermeiden sollten. Es ist jedoch viel besser lesbar und Sie sollten es meiner Meinung nach in nicht leistungskritischem Code empfehlen, der meiner Meinung nach mehr als 99 % des Codes ausmacht.
– Aaron
21. Februar 2019 um 10:39 Uhr
@pts Es gibt keine Stream-spezifischen Optimierungen, weder in javac auch nicht zur Laufzeit. Dies schließt die allgemeinen Optimierungen nicht aus, wie z. B. das Inlining des gesamten Codes, gefolgt von der Eliminierung redundanter Operationen. Im Prinzip könnte das Endergebnis so effizient sein wie die einfachen bedingten Ausdrücke, aber es ist eher unwahrscheinlich, dass es jemals dorthin kommt, da die Laufzeit den erforderlichen Aufwand nur für die heißesten Codepfade aufwenden würde.
– Holger
21. Februar 2019 um 10:40 Uhr
Tolle Lösung! Um die Lesbarkeit ein wenig zu erhöhen, würde ich vorschlagen, hinzuzufügen str4 zu den Parametern von Stream.of(...) und verwenden orElse(null) schlussendlich.
– Danielp
21. Februar 2019 um 23:12 Uhr
Eran
Wie wäre es mit einem ternären Bedingungsoperator?
Eigentlich sucht er nach “dem besten Ansatz, dies in Java8 zu tun”. Dieser Ansatz kann in Java8 verwendet werden, also hängt alles nur davon ab, was das OP unter “das Beste” versteht und auf welchen Gründen es die Entscheidung darüber stützt, was besser ist.
– Stultuske
21. Februar 2019 um 7:13 Uhr
Normalerweise mag ich verschachtelte Ternäre nicht, aber das sieht ziemlich sauber aus.
– JollyJoker
21. Februar 2019 um 8:59 Uhr
Dies ist ein großer Schmerz für jeden, der nicht jeden Tag verschachtelte ternäre Operatoren liest.
– Kubisch
21. Februar 2019 um 15:46 Uhr
@Cubic: Wenn Sie denken, dass es schwer zu analysieren ist, schreiben Sie einen Kommentar wie // take first non-null of str1..3. Sobald Sie wissen, was es tut, wird es leicht zu sehen, wie.
– Peter Cordes
22. Februar 2019 um 3:36 Uhr
@Cubic Doch das ist ein einfach wiederholtes Muster. Sobald Sie Zeile 2 geparst haben, haben Sie das ganze Ding geparst, egal wie viele Fälle enthalten sind. Und wenn Sie fertig sind, haben Sie gelernt, eine ähnliche Auswahl von zehn verschiedenen Fällen auf eine kurze und relativ einfache Weise auszudrücken. Das nächste Mal sehen Sie a ?: Leiter, Sie werden wissen, was es tut. (Übrigens, funktionale Programmierer kennen dies als (cond ...) Klauseln: Es ist immer ein Wächter, gefolgt von dem entsprechenden Wert, der verwendet werden soll, wenn der Wächter wahr ist.)
T firstNonNull<T>(T v0, T... vs) {
if(v0 != null)
return v0;
for(T x : vs) {
if (x != null)
return x;
}
return null;
}
Dann kann diese Art von Code geschrieben werden als
String s = firstNonNull(str1, str2, str3, str4);
Warum extra v0 Parameter?
– tobias_k
23. Februar 2019 um 10:08 Uhr
@tobias_k Der zusätzliche Parameter bei der Verwendung von varargs ist der idiomatische Weg in Java, 1 oder mehr Argumente anstelle von 0 oder mehr zu erfordern. (Siehe Punkt 53 von Effective Java, Ed. 3., der verwendet min als Beispiel.) Ich bin weniger davon überzeugt, dass dies hier angebracht ist.
– Nick
23. Februar 2019 um 15:49 Uhr
@Nick Ja, das habe ich mir schon gedacht, aber die Funktion würde ohne sie genauso gut funktionieren (tatsächlich genau gleich verhalten).
– tobias_k
23. Februar 2019 um 16:54 Uhr
Einer der Hauptgründe für die Übergabe eines zusätzlichen ersten Arguments besteht darin, das Verhalten bei der Übergabe eines Arrays explizit anzugeben. In diesem Fall möchte ich firstNonNull(arr) um arr zurückzugeben, wenn es nicht null ist. Wenn es war firstNonNull(T... vs) es würde stattdessen den ersten Nicht-Null-Eintrag in arr zurückgeben.
– Michael Anderson
24. Februar 2019 um 12:09 Uhr
Azro
Eine Lösung, die auf beliebig viele Elemente angewendet werden kann, kann sein:
Sie könnten sich eine Lösung wie unten vorstellen, aber die erste stellt sicher non nullity für alle Elemente
Stream.of(str1, str2, str3).....orElse(str4)
Warum extra v0 Parameter?
– tobias_k
23. Februar 2019 um 10:08 Uhr
@tobias_k Der zusätzliche Parameter bei der Verwendung von varargs ist der idiomatische Weg in Java, 1 oder mehr Argumente anstelle von 0 oder mehr zu erfordern. (Siehe Punkt 53 von Effective Java, Ed. 3., der verwendet min als Beispiel.) Ich bin weniger davon überzeugt, dass dies hier angebracht ist.
– Nik
23. Februar 2019 um 15:49 Uhr
@Nick Ja, das habe ich mir schon gedacht, aber die Funktion würde ohne sie genauso gut funktionieren (tatsächlich genau gleich verhalten).
– tobias_k
23. Februar 2019 um 16:54 Uhr
Einer der Hauptgründe für die Übergabe eines zusätzlichen ersten Arguments besteht darin, das Verhalten bei der Übergabe eines Arrays explizit anzugeben. In diesem Fall möchte ich firstNonNull(arr) um arr zurückzugeben, wenn es nicht null ist. Wenn es war firstNonNull(T... vs) es würde stattdessen den ersten Nicht-Null-Eintrag in arr zurückgeben.
– Michael Anderson
24. Februar 2019 um 12:09 Uhr
Sie können auch alle Strings in einem String-Array zusammenfassen und dann eine for-Schleife ausführen, um die Schleife zu überprüfen und zu unterbrechen, sobald sie zugewiesen wurde. Angenommen, s1, s2, s3, s4 sind alle Strings.
String[] arrayOfStrings = {s1, s2, s3};
s = s4;
for (String value : arrayOfStrings) {
if (value != null) {
s = value;
break;
}
}
Bearbeitet, um die Bedingung für die Standardeinstellung auf s4 zu setzen, wenn keine zugewiesen ist.
Du hast ausgelassen s4 (oder str4), dem zuzuordnen ist s am Ende, auch wenn es null ist.
– Anzeigename
22. Februar 2019 um 16:36 Uhr
12980600cookie-checkMehrere Nullprüfungen in Java 8yes
Java9
or
SyntaxString s = Optional.ofNullable(str1) .or(() -> Optional.ofNullable(str2)) .or(() -> Optional.ofNullable(str3)) .orElse(str4);
sieht nicht so gut aus wie dieStream.of
Ich würde ja.– Namann
21. Februar 2019 um 6:55 Uhr
Ich weiß, dass der Benutzer nach einer Java-8-spezifischen Lösung fragt, aber allgemein würde ich mitmachen
StringUtils.firstNonBlank()
– Mohamed Anees A
21. Februar 2019 um 12:09 Uhr
Das Problem ist, dass Java 8/streams dafür nicht die beste Lösung ist. Dieser Code riecht wirklich so, als wäre ein Refactor in Ordnung, aber ohne mehr Kontext ist es wirklich schwer zu sagen. Für den Anfang – warum sind drei Objekte, die wahrscheinlich so eng miteinander verwandt sind, nicht bereits in einer Sammlung?
– Bill K
21. Februar 2019 um 17:49 Uhr
@MohamedAneesA hätte die beste Antwort (als Kommentar) gegeben, aber in diesem Fall nicht die Quelle von StringUtils angegeben. Wenn Sie diese auf jeden Fall als eine Reihe separater Zeichenfolgen haben MÜSSEN, ist die Codierung als Varg-Methode wie “firstNonBlank” ideal. Die Syntax darin ist ein Array, das eine einfache For-Each-Schleife mit einer Rückgabe beim Auffinden von a erstellt Nicht-Null-Wert trivial und offensichtlich. In diesem Fall sind Java-8-Streams ein attraktives Ärgernis. Sie verleiten Sie dazu, etwas zu inlinen und zu komplizieren, das eine einfache Methode/Schleife sein sollte.
– Bill K
21. Februar 2019 um 17:55 Uhr
stackoverflow.com/q/2768054/31782
– n0rd
21. Februar 2019 um 20:48 Uhr