Apakah ada Java yang setara dengan COALESCE
fungsi SQL ? Yaitu, adakah cara untuk mengembalikan nilai non-null pertama dari beberapa variabel?
misalnya
Double a = null;
Double b = 4.4;
Double c = null;
Saya ingin entah bagaimana memiliki pernyataan yang akan mengembalikan nilai non-null pertama a
, b
dan c
- dalam hal ini, itu akan kembali b
, atau 4,4. (Sesuatu seperti metode sql - return COALESCE(a,b,c)
). Saya tahu bahwa saya dapat melakukannya secara eksplisit dengan sesuatu seperti:
return a != null ? a : (b != null ? b : c)
Tetapi saya bertanya-tanya apakah ada fungsi bawaan yang diterima untuk melakukan ini.
Jawaban:
Tidak, tidak ada.
Yang paling dekat yang bisa Anda dapatkan adalah:
Untuk alasan yang efisien, Anda dapat menangani kasus umum sebagai berikut:
sumber
coalesce(a, b)
, jikab
merupakan ekspresi yang rumit dana
tidaknull
,b
masih dievaluasi. Ini bukan kasus untuk?: Operator kondisional. Lihat jawaban ini .Apache Commons Lang 3
ObjectUtils.firstNonNull(T...)
Java 8 Stream
Stream.of(T...).filter(Objects::nonNull).findFirst().orElse(null)
sumber
Jika hanya ada dua variabel untuk diperiksa dan Anda menggunakan Guava, Anda dapat menggunakan MoreObjects.firstNonNull (T pertama, T kedua) .
sumber
Jika hanya ada dua referensi untuk diuji dan Anda menggunakan Java 8, Anda bisa menggunakannya
Jika Anda mengimpor statis Opsional, ekspresi tidak terlalu buruk.
Sayangnya kasus Anda dengan "beberapa variabel" tidak dimungkinkan dengan metode-Opsional. Sebagai gantinya Anda dapat menggunakan:
sumber
Mengikuti dari jawaban LES2, Anda dapat menghilangkan beberapa pengulangan dalam versi efisien, dengan memanggil fungsi kelebihan beban:
sumber
varargs
. Di sini, Anda membuang-buang memori dengan membuat bingkai tumpukan untuk setiapcoalesce()
panggilan bersarang . Memanggilcoalesce(a, b, c, d, e)
menciptakan hingga 3 frame stack untuk menghitung.Situasi ini memerlukan beberapa preprosesor. Karena jika Anda menulis fungsi (metode statis) yang memilih yang pertama bukan nilai nol, itu mengevaluasi semua item. Masalah jika beberapa item adalah panggilan metode (mungkin panggilan metode waktu yang mahal). Dan metode ini dipanggil bahkan jika setiap item sebelum mereka bukan nol.
Beberapa fungsinya seperti ini
harus digunakan tetapi sebelum mengkompilasi ke dalam kode byte harus ada preprocessor yang menemukan penggunaan "fungsi penggabungan" ini dan menggantinya dengan konstruksi seperti
Pembaruan 2014-09-02:
Berkat Java 8 dan Lambdas ada kemungkinan untuk memiliki perpaduan sejati di Jawa! Termasuk fitur penting: ekspresi tertentu dievaluasi hanya bila diperlukan - jika sebelumnya tidak nol, maka yang berikut tidak dievaluasi (metode tidak dipanggil, operasi komputasi atau disk / jaringan tidak dilakukan).
Saya menulis artikel tentang hal itu Java 8: coalesce - hledáme neNULLové hodnoty - (ditulis dalam bahasa Ceko, tapi saya harap contoh kode dapat dimengerti oleh semua orang).
sumber
Dengan Jambu Biji, Anda bisa melakukannya:
yang tidak melempar NPE jika keduanya
a
danb
sedangnull
.EDIT: Saya salah, itu melempar NPE. Cara yang benar seperti yang dikomentari oleh Michal Čizmazia adalah:
sumber
java.lang.NullPointerException: use Optional.orNull() instead of Optional.or(null)
Optional.fromNullable(a).or(Optional.fromNullable(b)).orNull()
Hanya untuk kelengkapan, kasus "beberapa variabel" memang mungkin, meskipun tidak elegan sama sekali. Misalnya, untuk variabel
o
,p
danq
:Harap dicatat penggunaan
orElseGet()
menghadiri untuk kasus yango
,p
danq
tidak variabel tapi ekspresi baik mahal atau dengan yang tidak diinginkan efek samping.Dalam kasus yang paling umum
coalesce(e[1],e[2],e[3],...,e[N])
Ini bisa menghasilkan ekspresi terlalu lama. Namun, jika kita mencoba untuk pindah ke dunia tanpa
null
, makav[i]
kemungkinan besar sudah bertipeOptional<String>
, bukan hanyaString
. Pada kasus ini,atau dalam hal ekspresi:
Selain itu, jika Anda juga pindah ke gaya fungsional-deklaratif,
o
,p
, danq
harus dari jenisSupplier<String>
seperti di:Dan kemudian keseluruhan
coalesce
dikurangi menjadio.get()
.Untuk contoh yang lebih konkret:
defaultAgeFromDatabase()
,,ageFromDatabase()
danageFromInput()
sudah akan kembaliOptional<Integer>
, secara alami.Dan kemudian
coalesce
menjadieffectiveAge.get()
atau hanyaeffectiveAge
jika kita senang denganSupplier<Integer>
.IMHO, dengan Java 8 kita akan melihat semakin banyak kode terstruktur seperti ini, karena sangat jelas dan efisien pada saat yang sama, terutama dalam kasus yang lebih kompleks.
Saya melewatkan kelas
Lazy<T>
yang memanggilSupplier<T>
hanya satu kali, tetapi malas, serta konsistensi dalam definisiOptional<T>
(yaituOptional<T>
-Optional<T>
operator, atau bahkanSupplier<Optional<T>>
).sumber
Anda dapat mencoba ini:
Berdasarkan tanggapan ini
sumber
Bagaimana dengan menggunakan pemasok ketika Anda ingin menghindari mengevaluasi beberapa metode mahal?
Seperti ini:
Dan kemudian menggunakannya seperti ini:
Anda juga dapat menggunakan metode kelebihan beban untuk panggilan dengan dua, tiga atau empat argumen.
Selain itu, Anda juga bisa menggunakan stream dengan sesuatu seperti ini:
sumber
Supplier
jika itu tetap akan diperiksa? Demi keseragaman?Bagaimana tentang:
Java ArrayList dengan mudah memungkinkan entri nol dan ekspresi ini konsisten terlepas dari jumlah objek yang dipertimbangkan. (Dalam bentuk ini, semua objek yang dipertimbangkan harus memiliki tipe yang sama.)
sumber
sumber
Double
jauh dari ideal. Saya hanya tidak sadar bahwa fungsi statis dapat diberikan parameter tipe. Saya pikir itu hanya kelas.