Hai, teman-teman! Kali ini kita kenalan dengan lambda dan stream di Java, dan pemicunya datang dari pemilik Warteg Canggih yang mulai serius membaca rekap harian. Dia tidak puas lagi dengan satu baris "Menu terlaris". Dia ingin tahu tiga menu terlaris sekaligus, menu apa saja yang belum laku hari ini, dan total porsi yang terjual.
Dengan cara yang kita pakai selama ini, setiap permintaan berarti satu perulangan baru, satu variabel penampung, dan beberapa if. Mencari menu terlaris saja di kasir versi 14 sudah butuh dua variabel dan satu if di dalam for-each. Tiga terlaris? Harus diurutkan dulu, dan itu jauh lebih panjang. cetakRekapHarian bisa jadi method paling gemuk di seluruh kasir.
TL;DR: Lambda adalah cara menulis method tanpa nama dalam satu ekspresi, seperti subtotal -> subtotal / 10, dan bisa dipakai di mana pun Java meminta functional interface (interface dengan satu method abstrak). Stream adalah alur pengolahan data: ambil dari sumber, saring dengan filter, ubah dengan map, urutkan dengan sorted, lalu tutup dengan operasi akhir seperti toList() atau sum(). Di kasir versi 15, rekap harian jadi bisa menampilkan tiga terlaris dan menu yang belum laku tanpa perulangan manual.
Yang Sudah Kita Pelajari
Artikel ini memakai bekal dari beberapa artikel sebelumnya:
- Method di Java: Parameter dan Return: struktur method berparameter dan bernilai balik yang kini bisa disingkat menjadi lambda.
- Pilar OOP di Java: interface
AturanDiskondengan satu method abstrak yang menjadi functional interface. - Collection di Java: ArrayList, LinkedList, HashMap, dan Map:
ArrayListdanLinkedHashMapdi kasir versi 14 yang menjadi sumber data stream.
Tujuan Artikel Ini
Di sini kamu akan belajar:
- Menulis lambda expression dan method reference untuk menyingkat kode interface.
- Memakai method bawaan collection seperti
removeIfdanforEachdengan lambda. - Menyaring data (
filter), mengubah bentuk (map), dan mengurutkan (sorted) dengan Stream API. - Menghitung rekap menu terlaris dan total porsi di kasir versi 15 tanpa perulangan manual.
- Mengetahui kapan harus memilih stream dan kapan tetap memakai for-loop biasa.
- Menghindari error umum pada stream seperti
IllegalStateExceptionakibat stream yang dipakai dua kali.
Kenalan Dulu: Apa Itu Lambda dan Stream di Java?
Lambda adalah potongan perilaku yang bisa dititipkan sebagai nilai, misalnya "saring yang porsinya lebih dari nol". Stream adalah alur yang mengalirkan data dari sebuah collection melewati langkah-langkah pengolahan. Keduanya hadir sejak Java 8, dan hampir selalu dipakai bersamaan: stream menentukan alurnya, lambda mengisi apa yang dikerjakan di setiap langkah.
Coba bayangin dapur warteg di jam makan siang. Piring kotor masuk ke ban berjalan, lalu melewati beberapa pos: pos pertama memisahkan piring dari gelas, pos kedua membilas, pos ketiga menyusun di rak. Ban berjalan itu stream. Instruksi di setiap pos, misalnya "ambil yang piring saja", itulah lambda. Pemilik dapur tidak perlu menulis ulang ban berjalannya setiap hari, cukup mengganti instruksi di posnya.
Oracle membahas keduanya di tutorial Lambda Expressions dan tutorial Aggregate Operations. Kita mulai dari lambda dulu, karena stream tidak bisa dipakai tanpanya.
Lambda Expression di Java: Method Tanpa Nama
Lambda expression adalah cara singkat menulis implementasi interface yang hanya punya satu method abstrak. Bentuknya parameter -> hasil, tanpa nama class, tanpa nama method, dan tanpa return kalau isinya cuma satu ekspresi. Java menebak sendiri tipe parameternya dari interface yang diminta.
Masih ingat DiskonJamSepi di artikel Pilar OOP? Satu file utuh hanya untuk satu baris return subtotal / 10. Sebelum ada lambda, kalau tidak mau membuat file baru, Java menyediakan anonymous class: class tanpa nama yang dibuat langsung di tempat:
AturanDiskon jamSepi = new AturanDiskon() {
@Override
public int hitung(int subtotal) {
return subtotal / 10;
}
};
Tidak perlu file baru, tapi tetap lima baris untuk satu ekspresi. Yang benar-benar penting dari semua itu cuma "subtotal masuk, subtotal / 10 keluar". Lambda membuang semua sisanya:
AturanDiskon jamSepi = subtotal -> subtotal / 10;
System.out.println(jamSepi.hitung(16000)); // 1600
Hasilnya sama persis dengan versi anonymous class. Kalau ingin membaca lebih jauh soal keduanya, saya pernah menulis anonymous class di Java dan fitur lambda expression di Java 8 di sufyan97.com.
Bentuk lambda menyesuaikan jumlah parameter dan panjang isinya:
| Bentuk | Contoh |
|---|---|
| Satu parameter, satu ekspresi | subtotal -> subtotal / 10 |
| Dua parameter | (nama, porsi) -> nama + ": " + porsi |
| Tanpa parameter | () -> System.out.println("Kasir dibuka") |
| Isi lebih dari satu baris | subtotal -> { int potong = subtotal / 10; return potong; } |
Functional Interface: Syarat Lambda Bisa Dipakai
Lambda tidak bisa ditaruh di sembarang tempat. Ia hanya bisa dipakai sebagai nilai untuk functional interface, yaitu interface yang punya tepat satu method abstrak. Dari situ Java tahu lambda itu sedang mengisi method yang mana.
AturanDiskon ternyata memenuhi syarat itu sejak awal, karena hanya punya hitung. Supaya niatnya jelas dan tidak ada yang tidak sengaja menambah method kedua, kita tandai dengan anotasi @FunctionalInterface:
@FunctionalInterface
interface AturanDiskon {
int hitung(int subtotal);
}
Kalau suatu hari ada yang menambah method abstrak kedua, compiler langsung protes, seperti dijelaskan di Javadoc FunctionalInterface. Java juga sudah menyediakan banyak functional interface siap pakai di paket java.util.function, misalnya Predicate untuk "ya atau tidak" dan Function untuk "ubah A jadi B". Method seperti filter dan map di stream memakai interface-interface itu.
Method Reference: Lambda yang Lebih Singkat Lagi
Kadang isi lambda cuma memanggil satu method yang sudah ada, misalnya menu -> menu.getNama(). Untuk kasus seperti itu, Java punya method reference: Menu::getNama. Artinya sama, "panggil getNama milik setiap menu", tapi lebih ringkas.
| Lambda | Method reference |
|---|---|
menu -> menu.getNama() |
Menu::getNama |
(a, b) -> Integer.sum(a, b) |
Integer::sum |
baris -> baris.getKey() |
Map.Entry::getKey |
Pakai method reference kalau memang lebih mudah dibaca, dan tetap pakai lambda kalau isinya lebih dari sekadar memanggil satu method. Aturan lengkapnya ada di tutorial Method References dari Oracle.
Lambda di Collection yang Sudah Kita Pakai
Sebelum masuk ke stream, lambda ternyata sudah bisa langsung mempersingkat kode collection dari artikel Collection. Beberapa method di List dan Map memang dirancang untuk menerima lambda.
removeIf menepati janji di artikel sebelumnya. Membuang semua "Es teh" dari daftar pesanan, yang dulu butuh Iterator dan while, sekarang satu baris:
pesanan.removeIf(p -> p.equals("Es teh"));
System.out.println(pesanan); // [Tempe orek, Nasi putih]
Map.merge menggantikan pola "ambil, tambah, simpan". Di kasir versi 14, kita menulis porsi.put(menu, porsi.getOrDefault(menu, 0) + jumlah). Dengan merge, kalau kunci belum ada nilainya langsung disimpan, kalau sudah ada keduanya digabung pakai fungsi yang kita berikan:
porsi.merge("Es teh", 2, Integer::sum);
porsi.merge("Es teh", 1, Integer::sum);
System.out.println(porsi); // {Es teh=3}
forEach menjalankan sesuatu untuk setiap isi. Di Map, lambda-nya menerima kunci dan nilai sekaligus, jadi tidak perlu lagi Map.Entry:
porsiHarian.forEach((nama, porsi) ->
System.out.println(String.format("%-14s%14s", nama, porsi + " porsi")));
sort dengan Comparator.comparing mengurutkan list berdasarkan apa pun yang kita pilih. Misalnya daftar menu dari yang termurah:
daftarMenu.sort(Comparator.comparing(Menu::getHarga));
// Es teh 3000, Tempe orek 4000, Nasi putih 5000, Telur balado 6000
Pilihan cara mengurutkan lainnya, seperti reversed() dan thenComparing, tercantum di Javadoc Comparator.
Stream di Java: Ban Berjalan untuk Data
Stream adalah alur pengolahan data yang terdiri dari tiga bagian: sumber (biasanya collection, lewat .stream()), nol atau lebih operasi perantara seperti filter, map, sorted, dan limit, lalu satu operasi akhir seperti toList(), count(), atau sum(). Stream tidak mengubah collection sumbernya, ia menghasilkan sesuatu yang baru.
Misalnya kita ingin daftar nama menu yang harganya paling mahal Rp4.000. Coba bandingkan bagaimana cara tradisional (native) dan cara stream menyelesaikannya:
// CARA NATIVE: Wajib membuat wadah penampung manual dulu, lalu menyaring di dalam perulangan
List<String> murah = new ArrayList<>();
for (Menu menu : daftarMenu) {
if (menu.getHarga() <= 4000) {
murah.add(menu.getNama());
}
}
System.out.println(murah); // [Tempe orek, Es teh, Sayur asem]
Bandingkan dengan cara stream:
// CARA STREAM: Tidak butuh wadah penampung, alurnya mengalir seperti kalimat
List<String> murah = daftarMenu.stream()
.filter(menu -> menu.getHarga() <= 4000)
.map(Menu::getNama)
.toList();
System.out.println(murah); // [Tempe orek, Es teh, Sayur asem]
Baca kode stream dari atas ke bawah: ambil daftar menu, saring yang harganya paling mahal Rp4.000, ambil namanya saja, kumpulkan jadi list.
| Aspek | Cara Native (For-Loop Tradisional) | Cara Stream + Lambda |
|---|---|---|
| Pola pikir | Imperatif: menjelaskan teknis langkah demi langkah (bikin list, putar loop, periksa if, simpan ke wadah) | Deklaratif: langsung menyatakan tujuan pengolahan datanya (saring, ubah bentuk, kumpulkan) |
| Wadah perantara | Wajib mendeklarasikan List kosong atau variabel penampung sementara |
Tidak butuh penampung sementara, data mengalir langsung di pipa (pipeline) |
| Data sumber | Rentan termodifikasi secara tidak sengaja di dalam perulangan | Tidak menyentuh atau mengubah collection aslinya sama sekali |
| Keterbacaan | Kurung kurawal bersarang (for di dalam if) |
Rantai method mengalir rapi dari atas ke bawah |
Operasi yang paling sering dipakai:
| Operasi | Jenis | Kegunaan |
|---|---|---|
filter(syarat) |
Perantara | Meloloskan data yang memenuhi syarat |
map(ubah) |
Perantara | Mengubah setiap data jadi bentuk lain |
sorted(cara) |
Perantara | Mengurutkan |
limit(n) |
Perantara | Mengambil n data pertama saja |
toList() |
Akhir | Mengumpulkan hasilnya jadi list |
count() |
Akhir | Menghitung jumlah data |
mapToInt(...).sum() |
Akhir | Menjumlahkan angka |
max(cara) |
Akhir | Mencari yang terbesar, hasilnya Optional |
Daftar lengkapnya ada di Javadoc Stream, dan cara kerja penjumlahan seperti sum() dibahas di tutorial Reduction dari Oracle. Contoh lain yang lebih fokus ke penjumlahan juga pernah saya tulis di penjumlahan dengan Stream Java.
Stream Itu Malas
Ada satu sifat stream yang sering mengejutkan: operasi perantara tidak langsung berjalan. Coba taruh println di dalam filter:
Stream<String> s = nama.stream().filter(n -> {
System.out.println("memeriksa " + n);
return n.startsWith("T");
});
System.out.println("stream sudah dibuat");
System.out.println(s.toList());
stream sudah dibuat
memeriksa Nasi putih
memeriksa Tempe orek
memeriksa Es teh
[Tempe orek]
"stream sudah dibuat" tercetak lebih dulu. filter baru benar-benar memeriksa data saat toList() dipanggil. Dokumentasi paket java.util.stream menyebut sifat ini lazy: perhitungan baru dijalankan saat operasi akhir dimulai. Akibatnya, stream tanpa operasi akhir tidak melakukan apa-apa sama sekali.
Stream Hanya Bisa Dipakai Sekali
Seperti ban berjalan yang sudah selesai mengantar piringnya, stream yang sudah dijalankan tidak bisa diputar ulang:
Stream<String> s = nama.stream();
System.out.println(s.count()); // 2
System.out.println(s.count()); // error
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
Solusinya sederhana: panggil .stream() lagi dari collection-nya setiap kali butuh alur baru. Stream itu murah dibuat, jadi tidak perlu disimpan di variabel.
Kasir Warteg Canggih Versi 15 dengan Lambda dan Stream di Java
Sekarang lambda dan stream dipasang di kasir. Alur menu, antrian, dan pesanan tidak berubah sama sekali. Yang berubah adalah bagian yang dulunya penuh perulangan untuk mengolah data.
Aturan Diskon Jam Sepi Jadi Lambda
DiskonJamSepi.java dihapus, karena satu baris lambda sudah cukup. Di main, aturan jam sepi tinggal ditulis langsung saat dibutuhkan:
// saat jam sepi, ganti dengan lambda: AturanDiskon aturanDiskon = subtotal -> subtotal / 10;
AturanDiskon aturanDiskon = new DiskonBertingkat();
DiskonBertingkat tetap jadi class, karena isinya beberapa if yang lebih enak dibaca sebagai class bernama daripada lambda panjang. Tidak semua implementasi interface harus jadi lambda.
Meringkas Pesanan dan Rekap dengan merge
// di ambilPesanan: ringkas daftar pesanan jadi porsi per menu
Map<Menu, Integer> porsi = new LinkedHashMap<>();
pesanan.forEach(item -> porsi.merge(item.getMenu(), item.getPorsi(), Integer::sum));
// di catatKeRekap: tambahkan porsi pembeli ini ke rekap harian
porsi.forEach((menu, jumlah) -> porsiHarian.merge(menu.getNama(), jumlah, Integer::sum));
Subtotal dengan mapToInt
int hitungSubtotal(Map<Menu, Integer> porsi) {
return porsi.entrySet().stream()
.mapToInt(baris -> baris.getKey().hitungHarga(baris.getValue()))
.sum();
}
mapToInt mengubah setiap baris jadi angka harga, lalu sum() menjumlahkannya. Tidak ada lagi variabel subtotal yang ditambah sedikit demi sedikit.
Rekap Harian yang Lebih Kaya
Ini bagian yang paling terasa. Tiga permintaan pemilik warteg dijawab oleh tiga alur stream:
int totalPorsi = porsiHarian.values().stream()
.mapToInt(Integer::intValue)
.sum();
// tiga menu dengan porsi terbanyak, yang tidak laku tidak ikut
List<String> terlaris = porsiHarian.entrySet().stream()
.filter(baris -> baris.getValue() > 0)
.sorted((a, b) -> b.getValue() - a.getValue())
.limit(3)
.map(baris -> baris.getKey() + " (" + baris.getValue() + ")")
.toList();
List<String> belumLaku = porsiHarian.entrySet().stream()
.filter(baris -> baris.getValue() == 0)
.map(Map.Entry::getKey)
.toList();
Coba baca alur terlaris sebagai kalimat: "ambil semua baris rekap, saring yang porsinya lebih dari nol, urutkan dari porsi terbanyak, ambil tiga teratas, ubah jadi teks, kumpulkan." Versi for-loop-nya butuh list penampung, pengurutan manual, dan penghitung.
Lambda (a, b) -> b.getValue() - a.getValue() adalah cara mengurutkan: hasil positif berarti b duluan, jadi yang porsinya lebih besar naik ke atas. Untuk angka kecil seperti porsi, pengurangan ini aman. Kalau angkanya bisa sangat besar, pakai Integer.compare(b.getValue(), a.getValue()) supaya tidak meluap. Kalau ada porsi yang sama, sorted mempertahankan urutan aslinya, jadi menu yang lebih dulu di daftar tetap tampil lebih dulu.
Contoh Satu Sesi
Budi memesan tempe orek dua porsi dan es teh, setelah membatalkan nasi putih. Pemilik warteg menambah perkedel, lalu Siti memesan perkedel, es teh, dan tempe orek:
Pesanan atas nama Siti
Perkedel x2 Rp6000
Es teh x1 Rp3000
Tempe orek x1 Rp4000
----------------------------
Subtotal Rp13000
Diskon Rp1000
TOTAL Rp12000
Rekap di akhir hari sekarang menjawab ketiga permintaan pemilik warteg:
REKAP HARI INI
----------------------------
Nasi putih 0 porsi
Tempe orek 3 porsi
Es teh 2 porsi
Telur balado 0 porsi
Sayur asem 0 porsi
Paket Hemat 0 porsi
Perkedel 2 porsi
----------------------------
Total porsi 7 porsi
Pembeli 2 orang
Omzet Rp22000
Terlaris: Tempe orek (3), Es teh (2), Perkedel (2)
Belum laku: Nasi putih, Telur balado, Sayur asem, Paket Hemat
Es teh dan perkedel sama-sama dua porsi, dan es teh tampil lebih dulu karena urutannya di menu memang lebih dulu.
Apa Saja yang Berubah dari Versi 14
DiskonJamSepi.javahilang, diganti satu baris lambda.AturanDiskondiberi@FunctionalInterface.- Pola "ambil, tambah, simpan" di map diganti
merge, baik untuk porsi per pembeli maupun rekap harian. hitungSubtotaljadi satu alur stream denganmapToIntdansum.- Rekap harian bertambah tiga baris: total porsi, tiga terlaris, dan menu yang belum laku.
- Menu, antrian, pembatalan pesanan, dan struk tidak berubah. Perilaku kasir di depan pembeli tetap sama.
Kapan Tetap Pakai For-Loop?
Setelah melihat stream, godaannya adalah mengganti semua perulangan. Jangan. Stream paling cocok untuk mengolah data yang sudah ada: menyaring, mengubah, mengurutkan, menjumlahkan. For-loop tetap lebih jelas untuk alur yang berinteraksi atau bergantung pada langkah sebelumnya.
Di kasir kita, contohnya:
bacaAngkamengulang sampai pengguna mengetik angka. Jumlah perulangannya tidak diketahui di awal, dan setiap langkah bergantung pada input baru. Ini pekerjaanwhile.- Menu utama
buka()berputar sampai kasir ditutup. Ini pekerjaando-while. tampilkanMenubutuh nomor uruti + 1untuk setiap menu. Bisa dipaksakan dengan stream, tapi for-loop biasa jauh lebih mudah dibaca.cetakKembalianmengurangi sisa uang langkah demi langkah. Setiap langkah mengubah variabelsisa, dan lambda tidak boleh mengubah variabel lokal di luarnya (lihat error di bagian berikut).
Ukurannya sederhana: kalau alurnya bisa dibaca sebagai "ambil data, saring, ubah, kumpulkan", pakai stream. Kalau alurnya "ulangi sampai sesuatu terjadi", pakai loop.
Error yang Sering Muncul Saat Memakai Lambda dan Stream di Java
| Gejala | Penyebab | Perbaikan |
|---|---|---|
local variables referenced from a lambda expression must be final or effectively final |
Lambda mencoba mengubah variabel lokal di luarnya, misalnya total += h |
Hitung lewat stream (mapToInt(...).sum()), atau pakai for-loop biasa |
IllegalStateException: stream has already been operated upon or closed |
Stream yang sama dipakai dua kali | Panggil .stream() lagi dari collection-nya |
| Tidak ada error, tapi tidak terjadi apa-apa | Stream tidak ditutup dengan operasi akhir | Tambahkan operasi akhir seperti toList(), count(), atau forEach |
NoSuchElementException: No value present |
.get() dipanggil pada Optional kosong, misalnya max dari stream yang tidak berisi apa-apa |
Pakai orElse(nilaiCadangan), atau cek isPresent() dulu |
Error pertama paling sering muncul. Kodenya terlihat wajar:
int total = 0;
harga.forEach(h -> total += h);
error: local variables referenced from a lambda expression must be final or effectively final
harga.forEach(h -> total += h);
^
Lambda boleh membaca variabel lokal di luarnya, tapi tidak boleh mengubahnya. Variabel yang tidak pernah diubah setelah diisi disebut effectively final, dan hanya variabel seperti itu yang boleh dipakai di dalam lambda. Cara stream untuk menjumlahkan adalah harga.stream().mapToInt(Integer::intValue).sum(), tanpa variabel penampung sama sekali.
Error keempat terjadi kalau rekap memakai max untuk mencari menu terlaris tapi belum ada yang terjual. max mengembalikan Optional, semacam kotak yang bisa kosong. Memanggil .get() pada kotak kosong langsung gagal. Itulah kenapa kasir versi 15 memakai filter dan limit lalu memeriksa isEmpty(), bukan max().get().
Penutup
Yang paling terasa setelah memakai stream bukan kodenya jadi lebih pendek, tapi cara membacanya berubah. For-loop bercerita tentang "bagaimana": siapkan penampung, ulangi, periksa, tambahkan. Stream bercerita tentang "apa": saring yang laku, urutkan, ambil tiga. Begitu terbiasa, membaca alur stream terasa seperti membaca catatan pemilik warteg, bukan membaca petunjuk mesin.
Sebagai latihan, tambahkan satu baris di rekap: rata-rata belanja per pembeli. Arah jawabannya: kamu sudah punya omzet dan jumlahPembeli, jadi ini cukup pembagian biasa, tidak perlu stream. Kalau kamu sempat tergoda memakai stream untuk ini, itu tanda bagus kamu mulai paham kapan stream cocok dan kapan tidak. Setelah itu, coba tantangan kedua: tampilkan menu yang harganya di atas rata-rata harga semua menu, dan di sini stream justru sangat membantu.
Di artikel berikutnya, Exception Handling di Java: try, catch, finally (yang terbit Jumat, 13 November 2026), kita kembali ke masalah yang sudah lama tertunda: bagaimana kasir menangani kesalahan dengan rapi, supaya tidak mati di tengah jam makan siang.
Daftar semua artikel seri ini ada di label Warteg Canggih Series. Kalau kamu baru pertama kali melihat stream, bagian mana yang paling terasa aneh: tanda ->, ::, atau alur yang ditulis bertingkat ke bawah? Cerita di kolom komentar, nanti bisa jadi bahan pembahasan lanjutan.
Source code lengkap artikel ini bisa dilihat di GitHub: 15-lambda-dan-stream-di-java
FAQ
Apa itu lambda expression di Java?
Lambda expression adalah cara singkat menulis implementasi functional interface, yaitu interface yang hanya punya satu method abstrak. Bentuknya parameter -> hasil, misalnya subtotal -> subtotal / 10. Lambda hadir sejak Java 8 dan banyak dipakai bersama stream dan method collection seperti removeIf dan forEach.
Apa itu stream di Java?
Stream adalah alur pengolahan data yang mengalirkan isi collection melewati operasi perantara seperti filter, map, dan sorted, lalu ditutup dengan operasi akhir seperti toList() atau sum(). Stream tidak mengubah collection sumbernya. Stream juga bersifat lazy, jadi operasi perantara baru berjalan saat operasi akhir dipanggil.
Apa bedanya map dan filter di stream Java?
filter menyaring data, jadi jumlah data bisa berkurang tapi bentuknya tetap sama. map mengubah setiap data jadi bentuk lain, jadi jumlahnya tetap tapi bentuknya berubah, misalnya dari object Menu jadi String nama menu. Keduanya sering dipakai berurutan dalam satu alur.
Apa itu method reference seperti Menu::getNama?
Method reference adalah bentuk ringkas lambda yang isinya hanya memanggil satu method yang sudah ada. Menu::getNama sama artinya dengan menu -> menu.getNama(). Pakai method reference kalau lebih mudah dibaca, dan tetap pakai lambda kalau isinya lebih dari satu pemanggilan method.
Kenapa lambda tidak boleh mengubah variabel lokal?
Variabel lokal yang dipakai di dalam lambda harus final atau effectively final, artinya tidak pernah diubah setelah diisi. Kalau lambda mencoba mengubahnya, misalnya total += h, compile gagal. Untuk menjumlahkan, pakai operasi stream seperti mapToInt(...).sum() atau for-loop biasa.
Referensi
- Lambda Expressions, The Java Tutorials (Oracle), diakses 22 Oktober 2026
- Method References, The Java Tutorials (Oracle), diakses 22 Oktober 2026
- Aggregate Operations, The Java Tutorials (Oracle), diakses 22 Oktober 2026
- Reduction, The Java Tutorials (Oracle), diakses 22 Oktober 2026
- Package java.util.stream, Java SE 21 API, diakses 22 Oktober 2026
- Interface Stream, Java SE 21 API, diakses 22 Oktober 2026
- Package java.util.function, Java SE 21 API, diakses 22 Oktober 2026
- Annotation Interface FunctionalInterface, Java SE 21 API, diakses 22 Oktober 2026
- Interface Comparator, Java SE 21 API, diakses 22 Oktober 2026
- Mengenal Anonymous Classes pada Bahasa Pemrograman Java, sufyan97.com, diakses 22 Oktober 2026
- Mengenal Fitur Lambda Expression pada Java 8, sufyan97.com, diakses 22 Oktober 2026
- Melakukan Penjumlahan (Sum) Menggunakan Stream pada Bahasa Pemrograman Java, sufyan97.com, diakses 22 Oktober 2026

Posting Komentar untuk "Lambda dan Stream di Java"