Apakah ekspresi lambda memiliki kegunaan selain menyimpan baris kode?
Apakah ada fitur khusus yang disediakan oleh lambda yang memecahkan masalah yang tidak mudah dipecahkan? Penggunaan tipikal yang pernah saya lihat adalah alih-alih menulis ini:
Comparator<Developer> byName = new Comparator<Developer>() {
@Override
public int compare(Developer o1, Developer o2) {
return o1.getName().compareTo(o2.getName());
}
};
Kita bisa menggunakan ekspresi lambda untuk mempersingkat kode:
Comparator<Developer> byName =
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());
(o1, o2) -> o1.getName().compareTo(o2.getName())
Comparator.comparing(Developer::getName)
Jawaban:
Ekspresi lambda tidak mengubah kumpulan masalah yang dapat Anda selesaikan dengan Java secara umum, tetapi yang pasti membuat pemecahan masalah tertentu lebih mudah, hanya untuk alasan yang sama kami tidak lagi memprogram dalam bahasa assembly. Menghapus tugas yang berlebihan dari pekerjaan programmer membuat hidup lebih mudah dan memungkinkan untuk melakukan hal-hal yang bahkan tidak akan Anda sentuh sebaliknya, hanya untuk jumlah kode yang harus Anda hasilkan (secara manual).
Tetapi ekspresi lambda tidak hanya menyimpan baris kode. Ekspresi Lambda memungkinkan Anda untuk menentukan fungsi , sesuatu yang dapat Anda gunakan kelas dalam anonim sebagai solusi sebelumnya, itulah mengapa Anda bisa mengganti kelas dalam anonim dalam kasus ini, tetapi tidak secara umum.
Terutama, ekspresi lambda didefinisikan secara independen ke antarmuka fungsional tempat mereka akan dikonversi, sehingga tidak ada anggota yang diwariskan yang dapat mereka akses, lebih jauh, mereka tidak dapat mengakses instance dari tipe yang mengimplementasikan antarmuka fungsional. Dalam ungkapan lambda,
this
dansuper
memiliki arti yang sama dengan konteks sekitarnya, lihat juga jawaban ini . Selain itu, Anda tidak dapat membuat variabel lokal baru yang membayangi variabel lokal dari konteks sekitarnya. Untuk tugas yang dimaksudkan dalam mendefinisikan suatu fungsi, tindakan ini menghapus banyak sumber kesalahan, tetapi juga menyiratkan bahwa untuk kasus penggunaan lain, mungkin ada kelas dalam anonim yang tidak dapat diubah menjadi ekspresi lambda, meskipun mengimplementasikan antarmuka fungsional.Lebih lanjut,
new Type() { … }
jaminan konstruksi untuk menghasilkan instance baru yang berbeda (sepertinew
biasa). Instance kelas dalam anonim selalu menyimpan referensi ke instans luarnya jika dibuat dalam non-static
konteks. Sebaliknya, ekspresi lambda hanya menangkap referensithis
saat dibutuhkan, yaitu jika mereka mengaksesthis
atau bukanstatic
anggota. Dan mereka menghasilkan instance dari identitas yang sengaja tidak ditentukan, yang memungkinkan implementasi untuk memutuskan pada waktu proses apakah akan menggunakan kembali instance yang ada (lihat juga " Apakah ekspresi lambda membuat objek di heap setiap kali dijalankan? ").Perbedaan ini berlaku untuk contoh Anda. Konstruksi kelas dalam anonim Anda akan selalu menghasilkan instance baru, juga dapat menangkap referensi ke instance luar, sedangkan Anda
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName())
adalah ekspresi lambda non-capturing yang akan mengevaluasi ke singleton dalam implementasi tipikal. Selanjutnya, itu tidak menghasilkan.class
file di hard drive Anda.Mengingat perbedaan terkait keduanya, semantik dan kinerja, ekspresi lambda dapat mengubah cara pemrogram akan memecahkan masalah tertentu di masa mendatang, tentu saja, juga karena API baru yang merangkul gagasan pemrograman fungsional yang memanfaatkan fitur bahasa baru. Lihat juga ekspresi lambda Java 8 dan nilai kelas satu .
sumber
Bahasa pemrograman bukan untuk dijalankan oleh mesin.
Mereka adalah untuk dipikirkan oleh para programmer .
Bahasa adalah percakapan dengan kompiler untuk mengubah pikiran kita menjadi sesuatu yang dapat dijalankan oleh mesin. Salah satu keluhan utama tentang Jawa dari orang-orang yang datang ke sana dari bahasa lain (atau tinggalkan itu untuk bahasa lain) yang digunakan untuk menjadi bahwa itu memaksa model mental tertentu pada programmer (yaitu semuanya kelas).
Saya tidak akan mempertimbangkan apakah itu baik atau buruk: semuanya timbal balik. Tetapi Java 8 lambda memungkinkan pemrogram untuk berpikir dalam kaitannya dengan fungsi , yang sebelumnya tidak dapat Anda lakukan di Java.
Ini sama dengan programmer prosedural yang belajar berpikir dalam istilah kelas ketika mereka datang ke Java: Anda melihat mereka secara bertahap berpindah dari kelas yang mengagungkan struct dan memiliki kelas 'pembantu' dengan sekumpulan metode statis dan beralih ke sesuatu yang lebih menyerupai desain OO rasional (mea culpa).
Jika Anda hanya menganggapnya sebagai cara yang lebih singkat untuk mengekspresikan kelas dalam anonim maka Anda mungkin tidak akan menganggapnya sangat mengesankan dengan cara yang sama seperti pemrogram prosedural di atas mungkin tidak menganggap kelas sebagai peningkatan yang besar.
sumber
Menyimpan baris kode dapat dilihat sebagai fitur baru, jika memungkinkan Anda untuk menulis sebagian besar logika dengan cara yang lebih pendek dan lebih jelas, yang membutuhkan lebih sedikit waktu bagi orang lain untuk membaca dan memahami.
Tanpa ekspresi lambda (dan / atau referensi metode),
Stream
pipeline akan jauh lebih sulit dibaca.Pikirkan, misalnya, bagaimana
Stream
pipeline berikut akan terlihat jika Anda mengganti setiap ekspresi lambda dengan instance kelas anonim.Itu akan:
Ini jauh lebih sulit untuk ditulis daripada versi dengan ekspresi lambda, dan jauh lebih rentan terhadap kesalahan. Ini juga lebih sulit untuk dipahami.
Dan ini adalah jalur pipa yang relatif pendek.
Agar ini dapat dibaca tanpa ekspresi lambda dan referensi metode, Anda harus menentukan variabel yang menampung berbagai contoh antarmuka fungsional yang digunakan di sini, yang akan memisahkan logika pipeline, sehingga lebih sulit untuk dipahami.
sumber
Comparator
karenasorted
perbandingannya secara alami. Mungkin mengubahnya menjadi membandingkan panjang string atau serupa, untuk membuat contoh menjadi lebih baik?compareToIgnoreCase
untuk membuatnya berperilaku berbeda darisorted()
.compareToIgnoreCase
masih merupakan contoh yang buruk, karena Anda cukup menggunakanString.CASE_INSENSITIVE_ORDER
komparator yang ada . Saran @ tobias_k untuk membandingkan berdasarkan panjang (atau properti lain yang tidak memiliki pembanding bawaan) lebih cocok. Dilihat dari contoh kode SO Q&A, lambda menyebabkan banyak implementasi komparator yang tidak perlu…Iterasi internal
Saat mengulang Koleksi Java, sebagian besar pengembang cenderung mendapatkan elemen dan kemudian memprosesnya . Ini, keluarkan item itu dan kemudian gunakan, atau masukkan kembali, dll. Dengan Java versi pra-8, Anda dapat mengimplementasikan kelas dalam dan melakukan sesuatu seperti:
Sekarang dengan Java 8 Anda dapat melakukan lebih baik dan lebih sedikit verbose dengan:
atau lebih baik
Perilaku sebagai argumen
Tebak kasus berikut:
Dengan antarmuka Java 8 Predicate Anda dapat melakukan lebih baik seperti ini:
Menyebutnya seperti:
Sumber: DZone - Mengapa Kami Membutuhkan Ekspresi Lambda di Jawa
sumber
numbers.forEach((Integer value) -> System.out.println(value));
ekspresi lambda dibuat dari dua bagian, satu di kiri simbol panah (->) yang mencantumkan parameternya dan yang di kanan berisi tubuhnya . Kompilator secara otomatis mengetahui bahwa ekspresi lambda memiliki tanda tangan yang sama dari satu-satunya metode antarmuka Konsumen yang tidak diimplementasikan.Ada banyak manfaat menggunakan lambda daripada kelas dalam berikut ini:
Buat kode lebih ringkas dan ekspresif tanpa memasukkan lebih banyak semantik sintaks bahasa. Anda sudah memberi contoh dalam pertanyaan Anda.
Dengan menggunakan lambda, Anda senang memprogram dengan operasi gaya fungsional pada aliran elemen, seperti transformasi pengurangan peta pada koleksi. melihat java.util.function & java.util.stream paket dokumentasi.
Tidak ada file kelas fisik yang dibuat untuk lambda oleh kompilator. Dengan demikian, itu membuat aplikasi yang Anda kirimkan lebih kecil. Bagaimana Memori diberikan ke lambda?
Compiler akan mengoptimalkan pembuatan lambda jika lambda tidak mengakses variabel di luar cakupannya, yang berarti instance lambda hanya dibuat sekali oleh JVM. untuk lebih jelasnya anda dapat melihat jawaban dari pertanyaan @Holger Apakah referensi metode caching ide yang baik di Java 8? .
Lambdas dapat mengimplementasikan antarmuka multi penanda selain antarmuka fungsional, tetapi kelas dalam anonim tidak dapat mengimplementasikan lebih banyak antarmuka, misalnya:
sumber
Lambda hanyalah gula sintaksis untuk kelas anonim.
Sebelum lambda, kelas anonim dapat digunakan untuk mencapai hal yang sama. Setiap ekspresi lambda dapat diubah menjadi kelas anonim.
Jika Anda menggunakan IntelliJ IDEA, itu dapat melakukan konversi untuk Anda:
sumber
Untuk menjawab pertanyaan Anda, kenyataannya adalah lambda tidak membiarkan Anda melakukan apa pun yang tidak dapat Anda lakukan sebelum java-8, melainkan memungkinkan Anda untuk menulis kode yang lebih ringkas . Manfaatnya, adalah kode Anda akan lebih jelas dan lebih fleksibel.
sumber
Satu hal yang belum saya lihat disebutkan adalah bahwa lambda memungkinkan Anda menentukan fungsionalitas tempat digunakan .
Jadi jika Anda memiliki beberapa fungsi pemilihan sederhana, Anda tidak perlu meletakkannya di tempat terpisah dengan sekumpulan boilerplate, Anda cukup menulis lambda yang ringkas dan relevan secara lokal.
sumber
Ya banyak keuntungan yang ada.
sumber