Ketika saya beralih koleksi menggunakan gula sintaksis baru Java 8, seperti
myStream.forEach(item -> {
// do something useful
});
Bukankah ini setara dengan cuplikan 'sintaks lama' di bawah?
myStream.forEach(new Consumer<Item>() {
@Override
public void accept(Item item) {
// do something useful
}
});
Apakah ini berarti Consumer
objek anonim baru dibuat di heap setiap kali saya mengulangi koleksi? Berapa banyak tumpukan ruang yang dibutuhkan? Apa implikasi kinerja yang dimilikinya? Apakah itu berarti saya lebih baik menggunakan gaya lama untuk loop ketika beralih pada struktur data multi-level yang besar?
Jawaban:
Ini setara tetapi tidak identik. Sederhananya, jika ekspresi lambda tidak menangkap nilai, itu akan menjadi singleton yang digunakan kembali pada setiap doa.
Perilaku tidak ditentukan secara spesifik. JVM diberi kebebasan besar tentang bagaimana mengimplementasikannya. Saat ini, JVM Oracle menciptakan (setidaknya) satu instance per ekspresi lambda (yaitu tidak berbagi instance antara ekspresi identik yang berbeda) tetapi membuat lajang untuk semua ekspresi yang tidak menangkap nilai.
Anda dapat membaca jawaban ini untuk lebih jelasnya. Di sana, saya tidak hanya memberikan deskripsi yang lebih rinci tetapi juga menguji kode untuk mengamati perilaku saat ini.
Ini dicakup oleh Spesifikasi Bahasa Java®, bab “ 15.27.4. Evaluasi Run-time tentang Ekspresi Lambda ”
Diringkas:
sumber
Ketika sebuah instance yang mewakili lambda dibuat secara sensitif tergantung pada isi yang tepat dari tubuh lambda Anda. Yaitu, faktor kuncinya adalah apa yang ditangkap lambda dari lingkungan leksikal. Jika tidak menangkap keadaan apa pun yang variabel dari kreasi ke kreasi, maka sebuah instance tidak akan dibuat setiap kali untuk setiap loop dimasukkan. Sebaliknya metode sintetis akan dihasilkan pada waktu kompilasi dan situs penggunaan lambda hanya akan menerima objek tunggal yang mendelegasikan metode tersebut.
Catatan lebih lanjut bahwa aspek ini tergantung pada implementasi dan Anda dapat mengharapkan perbaikan dan peningkatan di masa depan pada HotSpot menuju efisiensi yang lebih besar. Ada rencana umum untuk mis membuat objek ringan tanpa kelas yang sesuai penuh, yang hanya memiliki informasi yang cukup untuk meneruskan ke metode tunggal.
Berikut ini adalah artikel mendalam yang dapat diakses tentang topik ini:
http://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood
sumber
Anda memberikan contoh baru ke
forEach
metode. Setiap kali Anda melakukannya, Anda membuat objek baru tetapi tidak satu untuk setiap iterasi loop. Iterasi dilakukan di dalamforEach
metode menggunakan instance objek 'callback' yang sama sampai selesai dengan loop.Jadi memori yang digunakan oleh loop tidak tergantung pada ukuran koleksi.
Iya. Ini memiliki sedikit perbedaan pada tingkat yang sangat rendah tetapi saya tidak berpikir Anda harus peduli tentang mereka. Ekspresi Lamba menggunakan fitur invokedynamic daripada kelas anonim.
sumber