Temukan elemen
Sekarang kita sudah familiar dengan metode transformasi koleksi yang dirancang dengan elegan ini, tetapi tidak berguna untuk menemukan elemen. Namun metode filter lahir untuk ini.
Kami sekarang ingin menghapus nama yang dimulai dengan N dari daftar nama. Tentu saja mungkin tidak ada, dan hasilnya mungkin himpunan kosong. Mari kita implementasikan dulu menggunakan cara lama.
Copy kode kodenya sebagai berikut:
Daftar akhir<String> startWithN = ArrayList baru<String>();
for(String nama : teman) {
if(nama.mulaiDengan("N")) {
dimulaiDenganN.tambahkan(nama);
}
}
Menulis begitu banyak kode untuk acara sederhana seperti itu cukup bertele-tele. Kami pertama-tama membuat variabel dan kemudian menginisialisasinya ke koleksi kosong. Kemudian ulangi koleksi aslinya dan temukan nama-nama tersebut dimulai dengan huruf yang ditentukan. Jika ditemukan, dimasukkan ke dalam koleksi.
Mari gunakan metode filter untuk merekonstruksi kode di atas untuk melihat seberapa kuat kode tersebut.
Copy kode kodenya sebagai berikut:
Daftar akhir<String> dimulaiDenganN =
teman.stream()
.filter(nama -> nama.startsWith("N"))
.collect(Collectors.toList());
Metode filter menerima ekspresi lambda yang mengembalikan nilai Boolean. Jika ekspresi bernilai benar, elemen dalam konteks eksekusi tersebut akan ditambahkan ke kumpulan hasil; jika tidak, elemen tersebut akan dilewati. Apa yang akhirnya dikembalikan adalah Steam, yang hanya berisi elemen-elemen yang ekspresinya kembali benar. Terakhir kita menggunakan metode pengumpulan untuk mengubah koleksi menjadi sebuah daftar - kita akan membahas metode ini lebih mendalam di Menggunakan metode pengumpulan dan kelas Kolektor di halaman 52.
Mari cetak elemen dalam kumpulan hasil ini:
Copy kode kodenya sebagai berikut:
System.out.println(String.format("Ditemukan %d nama", startWithN.size()));
Terlihat jelas dari keluarannya bahwa metode ini telah menemukan semua elemen yang cocok dalam koleksi.
Copy kode kodenya sebagai berikut:
Menemukan 2 nama
Metode filter, seperti metode peta, juga mengembalikan iterator, tapi itu saja. Koleksi yang dikembalikan oleh peta berukuran sama dengan koleksi input, tetapi sulit untuk mengetahui filter apa yang dikembalikan. Rentang ukuran himpunan yang dikembalikannya, dari 0 hingga jumlah elemen dalam himpunan masukan. Tidak seperti peta, filter mengembalikan subset dari kumpulan masukan.
Sejauh ini kami sangat puas dengan kesederhanaan kode yang dibawa oleh ekspresi lambda, namun jika kami tidak berhati-hati, masalah redundansi kode perlahan akan mulai bertambah. Mari kita bahas masalah ini di bawah.
Penggunaan kembali ekspresi lambda
Ekspresi Lambda terlihat sangat ringkas, namun sebenarnya mudah untuk membuat kode menjadi berlebihan jika Anda tidak berhati-hati. Redundansi akan menyebabkan kualitas kode yang rendah dan kesulitan dalam pemeliharaan; jika kita ingin melakukan perubahan, kita harus mengubah beberapa kode terkait secara bersamaan.
Menghindari redundansi juga dapat membantu kami meningkatkan kinerja. Kode yang relevan terkonsentrasi di satu tempat, sehingga kita dapat menganalisis kinerjanya dan kemudian mengoptimalkan kode di sini, yang dapat dengan mudah meningkatkan kinerja kode.
Sekarang mari kita lihat mengapa penggunaan ekspresi lambda dapat dengan mudah menyebabkan redundansi kode, dan pertimbangkan cara menghindarinya.
Copy kode kodenya sebagai berikut:
Daftar terakhir<String> teman =
Arrays.asList("Brian", "Nate", "Neal", "Raju", "Sara", "Scott");
Daftar akhir<String> editor =
Arrays.asList("Brian", "Jackie", "John", "Mike");
Daftar terakhir<String> kawan =
Arrays.asList("Kate", "Ken", "Nick", "Paula", "Zach");
Kami ingin memfilter nama yang dimulai dengan huruf tertentu.
Kami ingin memfilter nama yang dimulai dengan huruf tertentu. Mari kita implementasikan saja menggunakan metode filter terlebih dahulu.
Copy kode kodenya sebagai berikut:
hitungan panjang terakhirFriendsStartN =
teman.stream()
.filter(nama -> nama.startsWith("N")).count();
hitungan panjang terakhirEditorsStartN =
editor.stream()
.filter(nama -> nama.startsWith("N")).count();
hitungan panjang terakhirComradesStartN =
kawan.stream()
.filter(nama -> nama.startsWith("N")).count();
Ekspresi Lambda membuat kode terlihat ringkas, namun tanpa disadari hal ini menyebabkan redundansi pada kode. Dalam contoh di atas, jika kita ingin mengubah ekspresi lambda, kita harus mengubah lebih dari satu tempat - dan hal ini tidak mungkin dilakukan. Untungnya, kita dapat menetapkan ekspresi lambda ke variabel dan menggunakannya kembali seperti objek.
Metode filter, penerima ekspresi lambda, menerima referensi ke antarmuka fungsional java.util.function.Predicate. Di sini, kompiler Java berguna lagi. Ini menghasilkan implementasi metode pengujian Predicate menggunakan ekspresi lambda yang ditentukan. Sekarang kita dapat secara lebih eksplisit meminta kompiler Java untuk membuat metode ini daripada membuatnya di tempat parameter ditentukan. Dalam contoh di atas, kita dapat secara eksplisit menyimpan ekspresi lambda ke dalam referensi bertipe Predikat, dan kemudian meneruskan referensi ini ke metode filter; hal ini dapat dengan mudah menghindari redundansi kode.
Mari kita refaktorisasi kode sebelumnya agar sesuai dengan prinsip KERING. (Jangan Ulangi Prinsip Anda - KERING - silakan merujuk ke buku The Pragmatic Programmer: From Journeyman to Master [HT00]).
Copy kode kodenya sebagai berikut:
Predikat akhir<String> startWithN = nama -> nama.startsWith("N");
hitungan panjang terakhirFriendsStartN =
teman.stream()
.filter(dimulaiDenganN)
.menghitung();
hitungan panjang terakhirEditorsStartN =
editor.stream()
.filter(dimulaiDenganN)
.menghitung();
hitungan panjang terakhirComradesStartN =
kawan.stream()
.filter(dimulaiDenganN)
.menghitung();
Sekarang daripada menulis ekspresi lambda lagi, kita menulisnya sekali dan menyimpannya dalam referensi tipe Predikat yang disebut startWithN. Dalam tiga panggilan filter berikut, kompiler Java melihat ekspresi lambda yang disamarkan sebagai Predikat, tersenyum dan menerimanya secara diam-diam.
Variabel yang baru diperkenalkan ini menghilangkan redundansi kode bagi kami. Namun sayangnya, seperti yang akan kita lihat nanti, musuh akan segera kembali untuk membalas dendam. Mari kita lihat senjata apa yang lebih ampuh yang bisa menghancurkan mereka untuk kita.