Gibt es ein Java-Äquivalent zur SQL- COALESCE
Funktion? Gibt es eine Möglichkeit, den ersten Nicht-Null-Wert mehrerer Variablen zurückzugeben?
z.B
Double a = null;
Double b = 4.4;
Double c = null;
Ich möchte irgendwie eine Erklärung haben, die den ersten Nicht-Null - Wert von wird zurückkehren a
, b
und c
- in diesem Fall würde es zurückgeben b
, oder 4.4. (So etwas wie die SQL-Methode - return COALESCE(a,b,c)
). Ich weiß, dass ich es explizit mit so etwas wie:
return a != null ? a : (b != null ? b : c)
Aber ich fragte mich, ob es eine eingebaute, akzeptierte Funktion gab, um dies zu erreichen.
Antworten:
Nein, gibt es nicht.
Der nächste, den Sie bekommen können, ist:
Aus effizienten Gründen können Sie die häufigsten Fälle wie folgt behandeln:
quelle
coalesce(a, b)
, wennb
es sich um einen komplexen Ausdruck handelt unda
nichtnull
,b
wird noch ausgewertet. Dies ist beim bedingten Operator ?: Nicht der Fall. Siehe diese Antwort .Apache Commons Lang 3
ObjectUtils.firstNonNull(T...)
Java 8 Stream
Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)
quelle
Wenn nur zwei Variablen überprüft werden müssen und Sie Guava verwenden, können Sie MoreObjects.firstNonNull (T first, T second) verwenden .
quelle
Wenn nur zwei Referenzen getestet werden müssen und Sie Java 8 verwenden, können Sie diese verwenden
Wenn Sie statisch importieren Optional ist der Ausdruck nicht schlecht.
Leider ist Ihr Fall mit "mehreren Variablen" mit einer optionalen Methode nicht möglich. Stattdessen könnten Sie verwenden:
quelle
In Anlehnung an die Antwort von LES2 können Sie einige Wiederholungen in der effizienten Version vermeiden, indem Sie die überladene Funktion aufrufen:
quelle
varargs
. Hier verschwenden Sie Speicher, indem Sie für jeden verschachteltencoalesce()
Aufruf einen Stapelrahmen erstellen . Beim Aufrufencoalesce(a, b, c, d, e)
werden bis zu 3 Stapelrahmen zur Berechnung erstellt.Diese Situation erfordert einen Präprozessor. Wenn Sie eine Funktion (statische Methode) schreiben, die den ersten Wert ungleich Null auswählt, werden alle Elemente ausgewertet. Es ist problematisch, wenn es sich bei einigen Elementen um Methodenaufrufe handelt (dies können zeitaufwändige Methodenaufrufe sein). Und diese Methoden werden auch dann aufgerufen, wenn ein Element vor ihnen nicht null ist.
Einige funktionieren so
sollte verwendet werden, aber vor dem Kompilieren in Bytecode sollte es einen Präprozessor geben, der die Verwendung dieser „Koaleszenzfunktion“ findet und sie durch eine Konstruktion wie ersetzt
Update 02.09.2014:
Dank Java 8 und Lambdas besteht die Möglichkeit, dass Java wirklich zusammenwächst! Einschließlich der entscheidenden Funktion: Bestimmte Ausdrücke werden nur bei Bedarf ausgewertet. Wenn der frühere nicht null ist, werden die folgenden nicht ausgewertet (Methoden werden nicht aufgerufen, Berechnungen oder Festplatten- / Netzwerkoperationen werden nicht ausgeführt).
Ich habe einen Artikel darüber geschrieben Java 8: coalesce - hledáme neNULLové hodnoty - (geschrieben auf Tschechisch, aber ich hoffe, dass Codebeispiele für alle verständlich sind).
quelle
Mit Guava können Sie Folgendes tun:
was NPE nicht wirft, wenn beide
a
undb
sindnull
.EDIT: Ich habe mich geirrt, es wirft NPE. Der richtige Weg, wie von Michal Čizmazia kommentiert, ist:
quelle
java.lang.NullPointerException: use Optional.orNull() instead of Optional.or(null)
Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull()
Nur der Vollständigkeit halber ist der Fall "mehrere Variablen" zwar möglich, aber überhaupt nicht elegant. Zum Beispiel für Variablen
o
,p
undq
:Bitte beachten Sie, dass Sie sich
orElseGet()
um den Fall kümmerno
müssenp
, dassq
es sich nicht um Variablen handelt, sondern um Ausdrücke, die entweder teuer sind oder unerwünschte Nebenwirkungen haben.Im allgemeinsten Fall
coalesce(e[1],e[2],e[3],...,e[N])
Dies kann zu lange Ausdrücke erzeugen. Wenn wir jedoch versuchen, uns in eine Welt ohne zu bewegen
null
, dannv[i]
sind wir höchstwahrscheinlich schon vom TypOptional<String>
, im Gegensatz zu einfachString
. In diesem Fall,oder im Fall von Ausdrücken:
Wenn Sie darüber hinaus auch zu einem funktionellen-deklarativem Stil bewegen,
o
,p
, undq
sollte vom Typ sein ,Supplier<String>
wie in:Und dann
coalesce
reduziert sich das Ganze einfach aufo.get()
.Für ein konkreteres Beispiel:
defaultAgeFromDatabase()
,ageFromDatabase()
UndageFromInput()
würde schon zurückkehrenOptional<Integer>
, natürlich.Und dann
coalesce
wird daseffectiveAge.get()
oder einfacheffectiveAge
wenn wir mit einem zufrieden sindSupplier<Integer>
.IMHO, mit Java 8 werden wir immer mehr Code sehen, der so strukturiert ist, da er extrem selbsterklärend und gleichzeitig effizient ist, insbesondere in komplexeren Fällen.
Ich vermisse eine Klasse
Lazy<T>
, dieSupplier<T>
nur einmal, aber träge, sowie Konsistenz in der Definition vonOptional<T>
(dhOptional<T>
-Optional<T>
Operatoren oder sogarSupplier<Optional<T>>
) aufruft .quelle
Sie können dies versuchen:
Basierend auf dieser Antwort
quelle
Wie wäre es mit Lieferanten, wenn Sie die Bewertung einer teuren Methode vermeiden möchten?
So was:
Und dann benutze ich es so:
Sie können auch überladene Methoden für die Aufrufe mit zwei, drei oder vier Argumenten verwenden.
Darüber hinaus können Sie auch Streams mit folgenden Elementen verwenden:
quelle
Supplier
einschließen, wenn es trotzdem überprüft wird? Aus Gründen der Einheitlichkeit?Wie wäre es mit:
Java ArrayList erlaubt bequemerweise Null-Einträge und dieser Ausdruck ist unabhängig von der Anzahl der zu berücksichtigenden Objekte konsistent. (In dieser Form müssen alle betrachteten Objekte vom gleichen Typ sein.)
quelle
quelle
Double
andere als ideal. Mir war nur nicht bewusst, dass statischen Funktionen Typparameter zugewiesen werden können. Ich dachte, es wäre nur Unterricht.