Czy istnieje odpowiednik funkcji SQL w języku Java COALESCE
? To znaczy, czy istnieje sposób na zwrócenie pierwszej niezerowej wartości kilku zmiennych?
na przykład
Double a = null;
Double b = 4.4;
Double c = null;
Chcę jakoś mieć oświadczenie, że wróci pierwszą wartość niezerową z a
, b
i c
- w tym przypadku, to wróci b
, lub 4,4. (Coś w rodzaju metody sql - powrót COALESCE(a,b,c)
). Wiem, że mogę to zrobić wprost za pomocą czegoś takiego:
return a != null ? a : (b != null ? b : c)
Ale zastanawiałem się, czy jest jakaś wbudowana, akceptowana funkcja, która to umożliwia.
Odpowiedzi:
Nie, nie ma.
Najbliższe możesz uzyskać:
Ze względów praktycznych możesz obsługiwać typowe przypadki w następujący sposób:
źródło
coalesce(a, b)
razieb
to kompleks ekspresja ia
nie jestnull
,b
jest jeszcze oceniany. Tak nie jest w przypadku operatora warunkowego?:. Zobacz tę odpowiedź .Apache Commons Lang 3
ObjectUtils.firstNonNull(T...)
Java 8 Stream
Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)
źródło
Jeśli są tylko dwie zmienne do sprawdzenia i używasz Guava, możesz użyć MoreObjects.firstNonNull (T pierwsza, T druga) .
źródło
Jeśli do przetestowania są tylko dwa odwołania i używasz języka Java 8, możesz użyć
Jeśli importujesz static Optional, wyrażenie nie jest takie złe.
Niestety Twój przypadek z „kilkoma zmiennymi” nie jest możliwy przy użyciu metody opcjonalnej. Zamiast tego możesz użyć:
źródło
Kontynuując odpowiedź LES2, możesz wyeliminować pewne powtórzenia w wydajnej wersji, wywołując przeciążoną funkcję:
źródło
varargs
. Tutaj marnujesz pamięć, tworząc ramkę stosu dla każdego zagnieżdżonegocoalesce()
wywołania. Wywołaniecoalesce(a, b, c, d, e)
tworzy do 3 ramek stosu do obliczenia.Ta sytuacja wymaga pewnego preprocesora. Ponieważ jeśli napiszesz funkcję (metodę statyczną), która wybiera pierwszą niezerową wartość, ocenia ona wszystkie elementy. Jest to problem, jeśli niektóre elementy są wywołaniami metod (mogą być czasochłonne wywołania metod). Te metody są wywoływane, nawet jeśli jakikolwiek element przed nimi nie jest pusty.
Niektóre działają w ten sposób
powinno być używane, ale przed skompilowaniem do kodu bajtowego powinien istnieć preprocesor, który znajdzie zastosowania tej „funkcji koalescencji” i zastąpi ją konstrukcją taką jak
Aktualizacja 2014-09-02:
Dzięki Java 8 i Lambdas istnieje możliwość prawdziwej koalescencji w Javie! W tym kluczowa cecha: poszczególne wyrażenia są oceniane tylko wtedy, gdy są potrzebne - jeśli poprzednie nie jest puste, to następne nie są oceniane (nie są wywoływane metody, nie są wykonywane obliczenia ani operacje na dysku / sieci).
Napisałem o tym artykuł Java 8: coalesce - hledáme neNULLové hodnoty - (napisany po czesku, ale mam nadzieję, że przykłady kodu są zrozumiałe dla każdego).
źródło
Z guawą możesz:
który nie zgłasza NPE, jeśli oba
a
ib
sąnull
.EDYCJA: Myliłem się, wyrzuca NPE. Prawidłowy sposób, jak skomentował Michał Čizmazia, to:
źródło
java.lang.NullPointerException: use Optional.orNull() instead of Optional.or(null)
Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull()
Dla zupełności, przypadek „kilku zmiennych” jest rzeczywiście możliwy, chociaż wcale nie jest elegancki. Na przykład, dla zmiennych
o
,p
orazq
:Proszę zwrócić uwagę na zastosowanie obsługi
orElseGet()
sprawy, żeo
,p
iq
nie są zmiennymi, ale wyrażeniami albo drogimi, albo z niepożądanymi skutkami ubocznymi.W najbardziej ogólnym przypadku
coalesce(e[1],e[2],e[3],...,e[N])
Może to generować zbyt długie wyrażenia. Jeśli jednak próbujemy przenieść się do świata bez
null
,v[i]
to najprawdopodobniej już jesteśmy typuOptional<String>
, a nie po prostuString
. W tym przypadku,lub w przypadku wyrażeń:
Ponadto, jeśli są również przeprowadzki do stylu funkcjonalnym-deklaratywny,
o
,p
, iq
powinny być typuSupplier<String>
jak w:A potem całość
coalesce
sprowadza się po prostu doo.get()
.Bardziej konkretny przykład:
defaultAgeFromDatabase()
,ageFromDatabase()
i naturalnieageFromInput()
już wróciOptional<Integer>
.A potem
coalesce
staje sięeffectiveAge.get()
lub po prostu,effectiveAge
jeśli jesteśmy zadowoleni zSupplier<Integer>
.IMHO, w Javie 8 zobaczymy coraz więcej kodu o takiej strukturze, ponieważ jest on niezwykle samo-wyjaśniający i jednocześnie wydajny, szczególnie w bardziej złożonych przypadkach.
Tęsknię za klasą,
Lazy<T>
która wywołujeSupplier<T>
tylko raz, ale leniwie, a także spójność w definicjiOptional<T>
(tj.Optional<T>
-Optional<T>
operatorów, a nawetSupplier<Optional<T>>
).źródło
Możesz spróbować tego:
Na podstawie tej odpowiedzi
źródło
Co powiesz na korzystanie z dostawców, jeśli chcesz uniknąć oceny jakiejś drogiej metody?
Lubię to:
A potem używając tego w ten sposób:
Możesz również użyć przeciążonych metod dla wywołań z dwoma, trzema lub czterema argumentami.
Ponadto możesz również użyć strumieni z czymś takim:
źródło
Supplier
skoro i tak będzie on sprawdzany? Ze względu na jednolitość?Co powiesz na:
Java ArrayList dogodnie zezwala na wpisy o wartości null, a to wyrażenie jest spójne niezależnie od liczby obiektów do rozważenia. (W tej formie wszystkie rozważane obiekty muszą być tego samego typu).
źródło
źródło
Double
jest daleki od ideału. Po prostu nie byłem świadomy, że statycznym funkcjom można nadać parametry typu. Myślałem, że to tylko zajęcia.