Koleksi adalah struktur yang menampung banyak nilai dalam satu variabel, dan hampir seluruh antarmuka Flutter dibangun di atasnya, mulai dari daftar item pada layar hingga Map yang memuat konfigurasi. Topik ini membahas List, Map, dan Set beserta literalnya, pemrosesan dengan where dan map, serta operator spread dengan collection-if dan collection-for yang nantinya digunakan setiap kali daftar widget disusun.
Program pertama: daftar belanja#
Contoh yang dijalankan menggunakan daftar belanja pribadi, lengkap dengan catatan stok dan item cadangan. Seluruh operasi berada di dalam satu fungsi main(), sehingga urutan perubahannya terbaca dari atas ke bawah. Simpan program berikut sebagai berkas belanja.dart, lalu jalankan perintah dart belanja.dart dari direktori tempat berkas itu berada.
// Membangun dan menumpuk koleksi: List, Map, Set, dan operator spread.
void main() {
// List: urutan terindeks dan boleh memuat duplikat.
var belanja = <String>['beras', 'telur', 'minyak'];
belanja.add('gula');
print('Daftar belanja : $belanja');
print('Jumlah item : ${belanja.length}');
print('Item pertama : ${belanja[0]}');
// Map: pasangan kunci-nilai.
var stok = <String, int>{'beras': 2, 'telur': 12, 'minyak': 1};
stok['gula'] = 1;
print('Stok telur : ${stok['telur']}');
for (final entry in stok.entries) {
print(' ${entry.key}: ${entry.value}');
}
// Set: elemen unik, duplikat otomatis dibuang.
var kategori = <String>{'pokok', 'pokok', 'sampingan'};
print('Kategori unik : $kategori');
// where dan map menghasilkan koleksi baru tanpa mengubah yang lama.
var itemPanjang = belanja.where((item) => item.length > 4).toList();
var itemBesar = belanja.map((item) => item.toUpperCase()).toList();
print('Item > 4 huruf : $itemPanjang');
print('Huruf besar : $itemBesar');
// Spread, spread null-aware, collection-if, dan collection-for.
List<String>? catatanTambahan; // masih null
var cadangan = <String>['tepung', 'susu'];
var belanjaLengkap = [
...belanja,
...?catatanTambahan,
if ((stok['minyak'] ?? 0) < 2) 'minyak (stok menipis)',
for (final item in cadangan) 'cadangan: $item',
];
print('Belanja lengkap: $belanjaLengkap');
}Daftar belanja : [beras, telur, minyak, gula]
Jumlah item : 4
Item pertama : beras
Stok telur : 12
beras: 2
telur: 12
minyak: 1
gula: 1
Kategori unik : {pokok, sampingan}
Item > 4 huruf : [beras, telur, minyak]
Huruf besar : [BERAS, TELUR, MINYAK, GULA]
Belanja lengkap: [beras, telur, minyak, gula, minyak (stok menipis), cadangan: tepung, cadangan: susu]Keluaran memperlihatkan perilaku inti dari ketiga koleksi. List menjaga urutan dan menerima duplikat, Map menghubungkan kunci dengan nilai, sedangkan Set membuang duplikat 'pokok' sehingga tersisa dua elemen. Dua baris berikutnya menunjukkan koleksi baru yang dihasilkan where dan map tanpa mengubah belanja. Baris terakhir memperlihatkan pembentukan belanjaLengkap yang memadukan spread, collection-if, dan collection-for dalam satu literal.
List, Map, dan Set#
List menyimpan nilai berurutan yang diakses melalui indeks mulai dari nol, dan belanja[0] menghasilkan 'beras'. Elemen baru ditambahkan melalui add(), dan length menyatakan jumlah elemennya. Map memasangkan kunci dengan nilai, sehingga stok['telur'] langsung menghasilkan stok telurnya, dan kunci baru ditambahkan melalui penugasan seperti stok['gula'] = 1. Set menampung nilai unik, dan penambahan nilai yang sudah ada tidak mengubah isinya.
Literal ketiganya terlihat pada program, yaitu kurung siku untuk List, kurung kurawal berisi pasangan kunci: nilai untuk Map, dan kurung kurawal berisi nilai tunggal untuk Set. Anotasi tipe seperti <String> dan <String, int> mengunci jenis isinya, sehingga memasukkan tipe lain ditolak Dart saat kompilasi. Literal juga dapat ditandai const, dan penambahan elemen pada konstanta semacam itu melempar error karena isinya memang tidak boleh berubah. Iterasi dilakukan dengan perulangan for-in, dan pada Map pola stok.entries menyediakan pasangan key dan value dalam satu langkah. Pilihan koleksi mengikuti kebutuhannya, yaitu urutan untuk List, pencarian berdasarkan kunci untuk Map, dan keunikan untuk Set.
Memproses koleksi dengan where dan map#
where menyaring elemen dengan fungsi predikat, yakni fungsi yang mengembalikan bool, sedangkan map mengubah setiap elemen menjadi bentuk lain. Keduanya tidak mengubah koleksi asalnya, melainkan menghasilkan koleksi baru, dan toList() mengumpulkan hasilnya menjadi List. Pada program, belanja.where((item) => item.length > 4) menghasilkan [beras, telur, minyak] karena gula adalah satu-satunya item yang tidak lebih panjang dari empat huruf. Ekspresi (item) => item.length > 4 adalah fungsi anonim, yaitu fungsi tanpa nama yang ditulis langsung di tempat pemanggilan.
forEach tersedia untuk menjalankan aksi pada setiap elemen tanpa menghasilkan koleksi baru, tetapi perulangan for-in lebih lazim dalam kode Dart karena tubuhnya dapat memuat logika yang lebih kompleks. Ketiga utilitas ini sering dirangkai, misalnya menyaring terlebih dahulu dengan where lalu mengubah hasilnya dengan map. Kegunaannya di Flutter terlihat ketika daftar data diubah menjadi daftar widget dalam satu ekspresi ringkas.
Operator spread dan collection-if#
Operator spread ... menyebarkan seluruh elemen sebuah koleksi ke dalam koleksi lain. Pada belanjaLengkap, ...belanja menambahkan empat item belanja ke literal baru. Variannya ...? menoleransi koleksi yang bernilai null, sehingga ...?catatanTambahan menambahkan nol elemen ketika variabel itu masih null, sedangkan ... tanpa tanda tanya melempar error ketika koleksinya bernilai null. Dengan begitu, sumber data yang opsional tidak perlu diperiksa terpisah.
Di dalam literal koleksi juga dapat muncul if dan for tanpa perlu membuat literal terpisah, kemampuan yang disebut collection-if dan collection-for. Pada program, if ((stok['minyak'] ?? 0) < 2) 'minyak (stok menipis)' menambahkan pengingat hanya apabila stoknya menipis, sedangkan for (final item in cadangan) 'cadangan: $item' menambahkan satu entri untuk setiap elemen cadangan. Kedua bentuk ini lazim digunakan untuk menyusun daftar widget di Flutter, misalnya daftar children pada Column yang isinya bergantung pada state aplikasi.
Kesalahan umum#
- Memodifikasi koleksi saat sedang diiterasi. Menambah atau menghapus elemen di dalam perulangan
for-inpada koleksi yang sama melempar errorConcurrent modification during iteration. Perbaikannya, iterasi dilakukan pada salinannya sepertibelanja.toList(), atau perubahan yang diinginkan dikumpulkan dahulu lalu diterapkan setelah perulangan selesai. - Menganggap akses
Mapdengan kunci yang tidak ada sebagai error. Ekspresistok['susu']untuk kunci yang belum terdaftar menghasilkan null tanpa pesan apa pun, dan kode berikutnya yang belum menangani null dapat melempar error. Perbaikannya, gunakanstok['susu'] ?? 0sebagai nilai bawaan, atau periksastok.containsKey('susu')terlebih dahulu. - Menggunakan
...pada koleksi yang mungkin null. Operator...melempar error ketika sumbernya bernilai null, sedangkan...?menambahkan nol elemen dalam keadaan yang sama. Perbaikannya, pilih...?untuk sumber data opsional dan gunakan...hanya untuk koleksi yang kehadirannya dijamin.
Ringkasan#
Listberurutan dan berindeks,Mapmemasangkan kunci dengan nilai, danSetmenyimpan elemen unik.wheremenyaring dengan predikat danmapmentransformasikan elemen, keduanya menghasilkan koleksi baru tanpa mengubah koleksi asal.- Operator
...menyebarkan elemen koleksi ke literal lain, sedangkan...?menoleransi koleksi yang bernilai null. - Collection-if dan collection-for menyisipkan elemen secara bersyarat dan berulang langsung di dalam literal, termasuk daftar widget Flutter.
Referensi#
- Collections — Dart
— Dokumentasi resmi
List,Map,Set, spread, dan collection-if. - Language — Dart — Halaman induk dokumentasi bahasa Dart yang memuat ringkasan seluruh fitur inti.