Java Pilihan - atauElse () vs atauElseGet ()

1. Pengenalan

API Opsional biasanya mempunyai dua kaedah yang boleh menyebabkan kekeliruan: atauElse () dan atauElseGet () .

Dalam tutorial ringkas ini, kita akan melihat perbezaan antara kedua-duanya dan meneroka kapan menggunakannya.

2. Tandatangan

Mari mulakan dengan asasnya dengan melihat tandatangan mereka:

public T orElse(T other) public T orElseGet(Supplier other)

Jelas sekali, orElse () mengambil apa-apa parameter jenis T manakala orElseGet () menerima antara muka yang berfungsi jenis Supplier pulangan objek jenis T .

Sekarang, berdasarkan Javadocs mereka:

  • orElse () : mengembalikan nilai jika ada, sebaliknya mengembalikan yang lain
  • atauElseGet (): mengembalikan nilai jika ada, sebaliknya memanggil yang lain dan mengembalikan hasil pemanggilannya

3. Perbezaan

Sangat mudah untuk menjadi bingung dengan definisi ringkas ini, jadi mari kita menggali lebih mendalam dan melihat beberapa senario penggunaan sebenar.

3.1. atau Lain-lain ()

Dengan andaian bahawa logger kami dikonfigurasi dengan betul, mari kita mulakan dengan menulis sekeping kod mudah:

String name = Optional.of("baeldung") .orElse(getRandomName());

Perhatikan bahawa getRandomName () adalah satu kaedah yang mengembalikan rawak nama dari Senarai daripada nama:

public String getRandomName() { LOG.info("getRandomName() method - start"); Random random = new Random(); int index = random.nextInt(5); LOG.info("getRandomName() method - end"); return names.get(index); }

Semasa melaksanakan kod kami, kami akan menemui mesej di bawah yang dicetak di konsol:

getRandomName() method - start getRandomName() method - end

Nama pemboleh ubah akan menahan "baeldung" pada akhir pelaksanaan kod.

Dengan itu, kita boleh membuat kesimpulan bahawa parameter orElse () dinilai walaupun mempunyai tidak kosong Pilihan .

3.2. atauElseGet ()

Sekarang, mari kita cuba menulis kod yang serupa menggunakan orElseGet () :

String name = Optional.of("baeldung") .orElseGet(() -> getRandomName());

Kod di atas tidak akan menggunakan kaedah getRandomName () .

Ingat (dari Javadoc) bahawa kaedah S upplier yang dilalui sebagai argumen hanya dilaksanakan apabila nilai Pilihan tidak ada.

Oleh itu, menggunakan orElseGet () untuk kes kami, akan menjimatkan masa kami untuk mengira nama rawak .

4. Mengukur Kesan Prestasi

Sekarang, untuk memahami perbezaan prestasi, mari gunakan JMH dan lihat beberapa nombor sebenar:

@Benchmark @BenchmarkMode(Mode.AverageTime) public String orElseBenchmark() { return Optional.of("baeldung").orElse(getRandomName()); }

Dan atauElseGet () :

@Benchmark @BenchmarkMode(Mode.AverageTime) public String orElseGetBenchmark() { return Optional.of("baeldung").orElseGet(() -> getRandomName()); }

Semasa melaksanakan kaedah penanda aras kami, kami mendapat:

Benchmark Mode Cnt Score Error Units orElseBenchmark avgt 20 60934.425 ± 15115.599 ns/op orElseGetBenchmark avgt 20 3.798 ± 0.030 ns/op

Seperti yang kita lihat, impak prestasi mungkin besar walaupun untuk senario kes penggunaan yang sederhana.

Nombor di atas mungkin sedikit berbeza, namun, atauElseGet () jelas mengungguli atauElse () untuk contoh tertentu kami.

Afterall, orElse () melibatkan pengiraan kaedah getRandomName () untuk setiap larian.

5. Apa Yang Penting?

Selain dari aspek prestasi, faktor lain yang perlu dipertimbangkan melibatkan:

  • Bagaimana jika kaedah itu akan melaksanakan beberapa logik tambahan? Contohnya membuat beberapa sisipan atau kemas kini DB
  • Walaupun kita memberikan objek ke parameter orElse () :
    String name = Optional.of("baeldung").orElse("Other")

    kami masih membuat objek "Lain" tanpa sebab

Itulah sebabnya penting bagi kita untuk membuat keputusan yang teliti di antara orElse () dan atauElseGet () bergantung pada keperluan kita - secara lalai, lebih masuk akal untuk menggunakan orElseGet () setiap kali kecuali objek lalai sudah dibina dan dapat diakses secara langsung .

6. Kesimpulannya

Dalam artikel ini, kami telah mengetahui nuansa antara kaedah Pilihan atauElse () dan OrElseGet () Pilihan . Kami juga menyedari bagaimana kadangkala konsep sederhana seperti itu dapat membawa makna yang lebih mendalam.

Seperti biasa, kod sumber lengkap boleh didapati di Github.