Konversi daftar
Mengubah koleksi menjadi koleksi baru semudah mengulanginya. Misalkan kita ingin mengubah nama dalam daftar menjadi huruf besar semua. Mari kita lihat beberapa metode implementasi.
String di Java tidak dapat diubah, sehingga tidak dapat diubah. Kita dapat membuat string baru untuk menggantikan elemen asli dalam daftar. Namun, jika Anda melakukan ini, daftar asli akan hilang; ada masalah lain. Daftar asli mungkin juga tidak dapat diubah, seperti yang dihasilkan oleh Arrays.asList(), sehingga mengubah daftar asli tidak akan berhasil. Kerugian lainnya adalah sulitnya dioperasikan secara paralel.
Membuat daftar huruf besar semua yang baru adalah pilihan yang baik.
Pada pandangan pertama, ini mungkin terdengar seperti saran yang lemah; kinerja adalah masalah yang kita semua pedulikan. Yang mengejutkan, pemrograman fungsional seringkali lebih berkinerja dibandingkan pemrograman imperatif, seperti yang kita bahas di Masalah Kinerja di halaman 153.
Mari kita mulai dengan menggunakan kumpulan ini untuk menghasilkan kumpulan huruf besar baru.
Copy kode kodenya sebagai berikut:
Daftar akhir<String> nama huruf besar = Daftar Array baru<String>();
for(String nama : teman) {
uppercaseNames.add(nama.toUpperCase());
}
Dalam kode imperatif, pertama-tama kita membuat daftar kosong, lalu mengisinya dengan nama huruf besar, menyisipkannya satu per satu sambil menelusuri daftar aslinya. Untuk meningkatkan ke versi fungsional, langkah pertama kita adalah mempertimbangkan untuk mengganti loop for dengan iterator internal forEach yang disebutkan dalam menelusuri daftar di halaman 19, seperti yang ditunjukkan dalam contoh berikut.
Copy kode kodenya sebagai berikut:
Daftar akhir<String> nama huruf besar = Daftar Array baru<String>();
friends.forEach(nama -> uppercaseNames.add(nama.toUpperCase()));
System.out.println(nama huruf besar);
Kami menggunakan iterator internal, tetapi kami juga harus membuat daftar baru dan memasukkan elemen ke dalamnya. Kami dapat meningkatkan lebih lanjut.
Menggunakan ekspresi lambda
Ada metode peta di antarmuka Stream yang baru diperkenalkan, yang dapat membantu kita menghindari variabilitas dan membuat kode terlihat lebih ringkas. Steam agak mirip dengan iterator koleksi, tetapi juga menyediakan fungsi yang lancar. Dengan menggunakan metode antarmuka ini, kita dapat menggabungkan serangkaian panggilan sehingga kode terbaca seperti urutan yang menjelaskan masalah, sehingga lebih mudah dibaca.
Metode peta Steam dapat digunakan untuk mengubah urutan masukan menjadi urutan keluaran - yang sangat cocok dengan apa yang ingin kita lakukan.
Copy kode kodenya sebagai berikut:
teman.stream()
.map(nama -> nama.toUpperCase())
.forEach(nama -> System.out.print(nama + " "));
Sistem.keluar.println();
Semua koleksi di JDK8 mendukung metode streaming ini, yang merangkum koleksi ke dalam instance Steam. Metode peta memanggil ekspresi lambda atau blok kode yang ditentukan untuk setiap elemen di Aliran. Metode map sangat berbeda dengan metode forEach. forEach hanya menjalankan fungsi tertentu pada elemen dalam koleksi. Metode map mengumpulkan hasil ekspresi lambda yang berjalan dan mengembalikan kumpulan hasil. Terakhir kami mencetak semua elemen menggunakan metode forEach.
Nama-nama dalam koleksi baru semuanya menggunakan huruf besar:
Copy kode kodenya sebagai berikut:
BRIAN NATE NEAL RAJU SARA SCOTT
Metode peta sangat cocok untuk mengubah suatu kumpulan masukan menjadi kumpulan keluaran baru. Metode ini memastikan bahwa rangkaian masukan dan keluaran memiliki jumlah elemen yang sama. Namun, elemen input dan output bisa berbeda tipenya. Dalam contoh ini, input dan output kita keduanya merupakan kumpulan string. Kita dapat meneruskan sepotong kode ke metode peta untuk mengembalikannya, misalnya, jumlah karakter yang terdapat dalam nama. Dalam hal ini masukannya masih berupa rangkaian string, namun keluarannya berupa rangkaian angka, seperti berikut ini.
Copy kode kodenya sebagai berikut:
teman.stream()
.peta(nama -> nama.panjang())
.forEach(hitungan -> Sistem.keluar.cetak(hitungan + " "));
Hasilnya adalah jumlah huruf pada setiap nama:
Copy kode kodenya sebagai berikut:
5 4 4 4 4 5
Versi ekspresi lambda yang lebih baru digunakan untuk menghindari operasi modifikasi eksplisit; Menulis dengan cara ini tidak lagi memerlukan inisialisasi koleksi kosong dan variabel sampah; variabel ini disembunyikan dalam implementasi yang mendasarinya.
Referensi metode penggunaan
Kita juga dapat menggunakan referensi metode untuk membuatnya lebih ringkas. Jika implementasi antarmuka fungsional perlu diteruskan, kompiler Java dapat menerima ekspresi lambda atau referensi metode. Dengan fitur ini, Anda dapat mengganti nama -> nama.toUpperCase() dengan String::toUpperCase, seperti ini:
Copy kode kodenya sebagai berikut:
teman.stream()
.map(String::toUpperCase)
.forEach(nama -> System.out.println(nama));
Ketika parameter diteruskan ke metode yang dihasilkan - implementasi metode abstrak dari antarmuka fungsional - Java akan memanggil metode toUpperCase dari parameter String. Referensi parameter ini disembunyikan di sini. Dalam skenario sederhana seperti di atas, kita dapat menggunakan referensi metode untuk menggantikan ekspresi lambda; untuk informasi lebih lanjut, lihat kapan referensi metode harus digunakan di halaman 26.
Copy kode kodenya sebagai berikut:
Seorang teman bertanya:
Kapan sebaiknya Anda menggunakan referensi metode?
Saat memprogram di Java, kita biasanya lebih banyak menggunakan ekspresi lambda daripada referensi metode. Namun ini tidak berarti bahwa referensi metode tidak penting atau tidak berguna. Ketika ekspresi lambda sangat pendek, ini merupakan alternatif yang baik untuk memanggil metode instan atau metode statis secara langsung. Dengan kata lain, jika ekspresi lambda hanya meneruskan parameter ke pemanggilan metode, kita harus menggunakan referensi metode.
Ekspresi lambda seperti ini mirip dengan apa yang dikatakan Tom Smykowski dalam film "Working with a Bug", tugasnya adalah "membawa persyaratan dari pelanggan ke insinyur perangkat lunak". Oleh karena itu, saya menyebut pola referensi metode refactoring ini sebagai pola cacing.
Selain ringkas, penggunaan referensi metode dapat lebih mencerminkan arti dan fungsi dari nama metode itu sendiri.
Di balik penggunaan referensi metode, compiler memainkan peran kunci. Objek target dan parameter yang direferensikan oleh metode ini akan diturunkan dari parameter yang diteruskan dalam metode yang dihasilkan. Hal ini memungkinkan Anda menggunakan referensi metode untuk menulis kode yang lebih ringkas daripada menggunakan ekspresi lambda. Namun, jika parameter harus diubah sebelum diteruskan ke metode atau hasil panggilan dikembalikan, kita tidak dapat menggunakan metode penulisan yang mudah ini.
Pada contoh sebelumnya, referensi metode mengacu pada metode instan. Referensi metode juga bisa merujuk ke metode statis dan metode yang menerima parameter. Kita akan melihat contohnya nanti.
Ekspresi Lambda dapat membantu kita melintasi koleksi dan mengubah koleksi. Seperti yang akan kita lihat di bawah, ini juga membantu kita dengan cepat memilih elemen dari koleksi.