Java Opsional - orElse () vs orElseGet ()

1. Perkenalan

API Opsional biasanya memiliki dua metode yang dapat menyebabkan kebingungan: orElse () dan orElseGet () .

Dalam tutorial singkat ini, kita akan melihat perbedaan antara keduanya dan mengeksplorasi kapan harus menggunakannya.

2. Tanda tangan

Mari kita mulai dengan dasar-dasarnya dengan melihat tanda tangan mereka:

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

Jelas, OrElse () mengambil parameter dari jenis T sedangkan orElseGet () menerima antarmuka fungsional dari jenis Pemasok yang kembali sebuah objek dari tipe T .

Sekarang, berdasarkan Javadocs mereka:

  • orElse () : mengembalikan nilai jika ada, jika tidak mengembalikan lainnya
  • orElseGet (): mengembalikan nilai jika ada, jika tidak, panggil other dan kembalikan hasil pemanggilannya

3. Perbedaan

Sangat mudah untuk sedikit bingung dengan definisi yang disederhanakan ini, jadi mari kita gali lebih dalam dan lihat beberapa skenario penggunaan yang sebenarnya.

3.1. orElse ()

Dengan asumsi kita telah mengkonfigurasi logger kita dengan benar, mari kita mulai dengan menulis sebuah kode sederhana:

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

Perhatikan bahwa getRandomName () adalah metode yang mengembalikan acak nama dari Daftar dari nama-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); }

Saat menjalankan kode kami, kami akan menemukan pesan di bawah ini yang tercetak di konsol:

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

Variabel Nama akan mengadakan “baeldung” pada akhir eksekusi kode.

Dengannya , kita dapat dengan mudah menyimpulkan bahwa parameter orElse () dievaluasi bahkan ketika Opsional tidak kosong .

3.2. orElseGet ()

Sekarang, mari kita coba menulis kode serupa menggunakan orElseGet () :

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

Kode di atas tidak akan memanggil metode getRandomName () .

Ingat (dari Javadoc) bahwa metode upplier S yang diteruskan sebagai argumen hanya dijalankan ketika nilai Opsional tidak ada.

Oleh karena itu, menggunakan orElseGet () untuk kasus kita akan menghemat waktu kita dalam menghitung nama acak .

4. Mengukur Dampak Kinerja

Sekarang, untuk juga memahami perbedaan kinerja, mari gunakan JMH dan lihat beberapa angka aktual:

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

Dan orElseGet () :

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

Saat menjalankan metode benchmark kami, kami mendapatkan:

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 dapat kita lihat, dampak kinerja mungkin besar bahkan untuk skenario kasus penggunaan yang sederhana.

Namun, angka di atas mungkin sedikit berbeda, orElseGet () jelas mengungguli orElse () untuk contoh khusus kami.

Lagipula, orElse () melibatkan komputasi metode getRandomName () untuk setiap proses.

5. Apa yang Penting?

Terlepas dari aspek kinerja, faktor lain yang patut dipertimbangkan meliputi:

  • Bagaimana jika metode tersebut akan menjalankan beberapa logika tambahan? Misalnya membuat beberapa penyisipan atau pembaruan DB
  • Bahkan ketika kita menetapkan objek ke parameter orElse () :
    String name = Optional.of("baeldung").orElse("Other")

    kami masih membuat objek "Lainnya" tanpa alasan

Dan itulah mengapa penting bagi kita untuk membuat keputusan yang cermat antara orElse () dan orElseGet () bergantung pada kebutuhan kita - secara default, lebih masuk akal untuk menggunakan orElseGet () setiap kali kecuali objek default sudah dibuat dan dapat diakses secara langsung .

6. Kesimpulan

Dalam artikel ini, kita telah mempelajari perbedaan antara metode Opsional orElse () dan OrElseGet () . Kami juga memperhatikan bagaimana terkadang konsep sederhana seperti itu dapat memiliki makna yang lebih dalam.

Seperti biasa, kode sumber lengkap dapat ditemukan di Github.