Saya mencoba memahami perbedaan antara metode Optional<T>.orElse()
dan Optional<T>.orElseGet()
metode.
Deskripsi untuk orElse()
metode ini adalah "Kembalikan nilainya jika ada, jika tidak kembalikan yang lain."
Sementara, deskripsi untuk orElseGet()
metode ini adalah "Kembalikan nilainya jika ada, jika tidak panggil orang lain dan kembalikan hasil dari pemanggilan itu."
The orElseGet()
Metode mengambil antarmuka fungsional Supplier, yang pada dasarnya tidak mengambil parameter dan kembali T
.
Dalam situasi apa Anda perlu menggunakan orElseGet()
? Jika Anda memiliki sebuah metode T myDefault()
mengapa tidak Anda hanya melakukan optional.orElse(myDefault())
daripada optional.orElseGet(() -> myDefault())
?
Tampaknya tidak orElseGet()
menunda eksekusi dari ekspresi lambda ke beberapa waktu kemudian atau lebih, jadi apa gunanya? (Saya akan berpikir bahwa itu akan lebih berguna jika mengembalikan yang lebih aman Optional<T>
yang get()
tidak pernah melempar NoSuchElementException
dan isPresent()
selalu mengembalikan true ... tetapi ternyata tidak, itu hanya mengembalikan T
seperti orElse()
).
Apakah ada perbedaan lain yang saya lewatkan?
orElseGet
hanya memanggil pemasok jika nilainya tidak ada.orElse()
inimyDefault()
metode masih disebut, tetapi nilai kembali hanya tidak digunakan.orElseGet()
dapat mengakibatkan beberapa bug serius: medium.com/alphadev-thoughts/…Jawaban:
Ambil dua skenario ini:
Jika
opt
tidak mengandung nilai, keduanya memang setara. Tetapi jikaopt
memang mengandung nilai, berapa banyakFoo
objek yang akan dibuat?Ps: tentu saja dalam contoh ini perbedaannya mungkin tidak akan terukur, tetapi jika Anda harus mendapatkan nilai default Anda dari layanan web jarak jauh misalnya, atau dari database, tiba-tiba menjadi sangat penting.
sumber
Foo
objek baru , sedangkan dalam kasus pertama itu akan membuatnya, tetapi tidak menggunakannya jika ada nilai di dalamOptional
.System.out.println()
ini bukan perhitungan tetapi pernyataan yang menghasilkan efek samping yang dapat diamati. Dan saya sudah mengatakan bahwa efek samping yang dapat diamati akan menghambat optimasi (aliran output konsol adalah sumber daya eksternal).Jawaban singkat:
Optional.isPresent()
nilainyaOptional.isPresent() == false
Dalam kode nyata, Anda mungkin ingin mempertimbangkan pendekatan kedua saat sumber daya yang dibutuhkan mahal untuk didapatkan .
Untuk lebih jelasnya, perhatikan contoh berikut dengan fungsi ini:
Perbedaannya adalah sebagai berikut:
Ketika
optional.isPresent() == false
, tidak ada perbedaan antara dua cara. Namun, kapanoptional.isPresent() == true
,orElse()
selalu memanggil fungsi berikutnya apakah Anda menginginkannya atau tidak.Akhirnya, test case yang digunakan adalah sebagai berikut:
Hasil:
Kode:
sumber
Optional.isPresent() == false
(false, not true)Optional.orElse
yang menyatakanIf a value is present, returns the value, otherwise returns other
dapat menyiratkan perilaku ini ...orElse()
berperilaku mirip denganfinally
ditry-catch
ekspresi. Apakah saya benar?Saya sampai di sini untuk masalah yang Kudo sebutkan.
Saya berbagi pengalaman saya untuk orang lain.
orElse
, atauorElseGet
, itulah pertanyaannya:cetakan
orElse
mengevaluasi nilai B () secara interdependen dari nilai opsional. KarenaorElseGet
itu malas.sumber
B()
ke metode bernamaorElse()
atauabc()
tidak ada bedanya,B()
dievaluasi.or
menyesatkan awalan pengembang (termasuk saya ketika saya bertanya masalah) dengan berpikir bahwa itu adalah operasi hubungan arus pendek, karena itulah yang kita digunakan untuk dalam kondisi boolean. Namun, bukan, itu hanya nama metode yang adaor
di awalannya, sehingga argumennya akan dievaluasi, terlepas dari apakahOptional
membawa nilai atau tidak. Sangat disayangkan bahwa penamaan itu membingungkan, bukan karena kita dapat melakukan apa-apa.Saya akan mengatakan perbedaan terbesar antara
orElse
danorElseGet
datang ketika kami ingin mengevaluasi sesuatu untuk mendapatkan nilai baru dalamelse
kondisi tersebut.Pertimbangkan contoh sederhana ini -
Sekarang mari kita ubah contoh di atas untuk digunakan
Optional
bersama denganorElse
,Sekarang mari kita ubah contoh di atas untuk digunakan
Optional
bersama denganorElseGet
,Ketika
orElse
dipanggil,apicall().value
dievaluasi dan diteruskan ke metode. Padahal, dalam halorElseGet
evaluasi hanya terjadi jikaoldValue
kosong.orElseGet
memungkinkan evaluasi malas.sumber
Contoh berikut harus menunjukkan perbedaan:
Jawabannya muncul di dokumen juga.
public T orElseGet(Supplier<? extends T> other)
:Itu
Supplier
tidak akan dipanggil jikaOptional
hadiah. sedangkan,public T orElse(T other)
:Jika
other
adalah metode yang mengembalikan string, itu akan dipanggil, tetapi nilainya tidak akan dikembalikan jikaOptional
ada.sumber
Perbedaannya cukup halus dan jika Anda tidak terlalu memperhatikan maka Anda akan tetap menggunakannya dengan cara yang salah.
Cara terbaik untuk memahami perbedaan antara
orElse()
danorElseGet()
adalah bahwaorElse()
akan selalu dieksekusi jikaOptional<T>
ini nol atau tidak , TapiorElseGet()
hanya akan dieksekusi ketikaOptional<T>
adalah nol .Arti kamus orElse adalah : - mengeksekusi bagian ketika sesuatu tidak ada, tetapi di sini bertentangan, lihat contoh di bawah ini:
Benchmark :
Semoga ini menghilangkan keraguan orang-orang seperti saya yang menginginkan contoh dasar yang sangat mendasar :)
sumber
Pertama-tama periksa deklarasi kedua metode.
1) OrElse: Jalankan logika dan berikan hasil sebagai argumen.
2) OrElseGet: Jalankan logika jika nilai di dalam opsional adalah nol
Beberapa penjelasan tentang deklarasi di atas: Argumen "Optional.orElse" selalu dieksekusi terlepas dari nilai objek dalam opsional (nol, kosong atau dengan nilai). Selalu pertimbangkan hal yang disebutkan di atas dalam pikiran saat menggunakan "Optional.orElse", jika tidak, gunakan "Optional.orElse" bisa sangat berisiko dalam situasi berikut.
Risiko-1) Masalah Pencatatan: Jika konten di dalam orElse berisi pernyataan log apa pun: Dalam hal ini, Anda pada akhirnya akan mencatatnya setiap waktu.
Risiko-2) Masalah Kinerja: Jika konten di dalam orElse padat waktu: Konten intensif waktu dapat berupa operasi DB panggilan, panggilan API, pembacaan file. Jika kami menaruh konten seperti itu di orElse (), sistem pada akhirnya akan mengeksekusi kode yang tidak digunakan.
Risiko-3) Keadaan Ilegal atau Masalah Bug: Jika konten di dalam orElse mengubah beberapa status objek: Kami mungkin menggunakan objek yang sama di tempat lain, misalkan dalam fungsi Optional.map dan itu dapat menempatkan kami dalam bug kritis.
Lalu, Kapan kita bisa menggunakan OrElse ()? Lebih suka menggunakan orElse ketika nilai default adalah beberapa objek konstan, enum. Dalam semua kasus di atas kita bisa menggunakan Optional.orElseGet () (yang hanya dijalankan ketika Opsional berisi nilai yang tidak kosong) alih-alih Optional.orElse (). Mengapa?? Di orElse, kami meneruskan nilai hasil default, tetapi di orElseGet kami melewati Pemasok dan metode Pemasok hanya dijalankan jika nilai dalam Opsional adalah nol.
Pengambilan kunci dari ini:
Saya telah menjelaskan hal ini pada poin-2 ( “Optional.map/Optional.orElse”! = “If / else” ) blog medium saya. Gunakan Java8 sebagai programmer bukan sebagai coder
sumber
Mempertimbangkan kode berikut:
jika kita mendapatkan
value
cara ini:Optional.<String>ofNullable(null)
, tidak ada perbedaan antara orElseGet () dan OrElse (), tetapi jika kita mendapatkanvalue
cara ini:Optional.<String>ofNullable("test")
,orelesMethod()
diorElseGet()
tidak akan dipanggil tetapi dalamorElse()
itu akan disebutsumber