dartmapMenengah4 mnt baca

Manipulasi Map Lanjutan

putIfAbsent, update, map transformasi, dan menggabung map.

Lebih dari sekadar simpan-ambil

Modul map dasar mengajarkan akses dan assignment. Tapi Map punya method canggih untuk pola umum: "isi jika belum ada", "update berdasarkan nilai lama", "ubah semua nilai", "gabung dua map".

Analogi: map dasar itu seperti loker (simpan/ambil). Method lanjutan itu seperti resepsionis pintar: "kalau loker kosong, isi dengan ini", "kalau sudah ada, gabungkan".

Kenapa method ini ada?

Karena pola "cek lalu isi" ditulis manual rawan race logika dan bertele-tele. Method bawaan melakukannya atomik dalam satu panggilan yang jelas.

putIfAbsent dan update

dart
void main() {
  var stok = {'apel': 10, 'mangga': 5};

  // putIfAbsent: isi HANYA jika kunci belum ada
  stok.putIfAbsent('apel', () => 99); // diabaikan, sudah ada
  stok.putIfAbsent('pisang', () => 7); // ditambahkan
  print(stok); // {apel: 10, mangga: 5, pisang: 7}

  // update: ubah berdasarkan nilai LAMA
  stok.update('apel', (lama) => lama + 5); // 10 -> 15
  print(stok['apel']); // 15

  // update dengan ifAbsent: aman untuk kunci baru
  stok.update('durian', (lama) => lama + 1, ifAbsent: () => 1);
  print(stok['durian']); // 1
}

Perhatikan parameternya berupa fungsi: () => 7 dan (lama) => lama + 5. Fungsi hanya dipanggil jika dibutuhkan (lazy), sehingga komputasi mahal tidak sia-sia.

Contoh kedua, menghitung frekuensi kata (kasus klasik):

dart
void main() {
  var kata = ['apel', 'mangga', 'apel', 'pisang', 'apel', 'mangga'];

  var frekuensi = <String, int>{};
  for (var k in kata) {
    frekuensi.update(k, (lama) => lama + 1, ifAbsent: () => 1);
  }
  print(frekuensi); // {apel: 3, mangga: 2, pisang: 1}
}

Satu baris update menggantikan if-else manual 4 baris. Pola ini muncul di analitik, voting, dan agregasi.

map(): transformasi pasangan

dart
void main() {
  var harga = {'apel': 5000, 'mangga': 8000};

  // Ubah semua nilai: tambah pajak 10%
  var denganPajak = harga.map((k, v) => MapEntry(k, (v * 1.1).toInt()));
  print(denganPajak); // {apel: 5500, mangga: 8800}

  // Ubah kunci jadi kapital
  var kapital = harga.map((k, v) => MapEntry(k.toUpperCase(), v));
  print(kapital); // {APEL: 5000, MANGGA: 8000}
}

map pada Map mengembalikan Map baru lewat MapEntry(kunciBaru, nilaiBaru). Mirip map pada List, tapi untuk pasangan.

Menggabung map: addAll dan spread

dart
void main() {
  var a = {'x': 1, 'y': 2};
  var b = {'y': 99, 'z': 3};

  // addAll: timpa ke map pertama (mutatif)
  var gabung1 = {...a};
  gabung1.addAll(b);
  print(gabung1); // {x: 1, y: 99, z: 3}

  // spread: buat map baru, yang terakhir menang
  var gabung2 = {...a, ...b};
  print(gabung2); // {x: 1, y: 99, z: 3}
}

Kunci duplikat selalu dimenangkan yang terakhir. Ini cara idiomatis menggabung konfigurasi default dengan konfigurasi pengguna.

Kesalahan umum

1. update tanpa ifAbsent untuk kunci baru

dart
void main() {
  var m = <String, int>{};
  // m.update('a', (v) => v + 1); // ERROR: kunci tidak ada!
  m.update('a', (v) => v + 1, ifAbsent: () => 1); // BENAR
  print(m); // {a: 1}
}

2. putIfAbsent dengan nilai langsung

dart
void main() {
  var m = <String, int>{};
  // m.putIfAbsent('a', 5); // ERROR: butuh fungsi!
  m.putIfAbsent('a', () => 5); // BENAR
  print(m);
}

Parameternya fungsi agar komputasi malas: jika kunci sudah ada, fungsi tidak dipanggil.

3. Mengira map() mengubah asli

Seperti List, map pada Map mengembalikan Map BARU. Simpan hasilnya.

Kesimpulan

putIfAbsent (isi jika kosong), update (ubah berdasar nilai lama + ifAbsent), map dengan MapEntry (transformasi), spread/addAll (gabung). Empat perkakas ini menuntaskan 90% manipulasi map tingkat lanjut.

Catatan teknis: update bersifat atomik untuk satu pemanggilan, aman dari kondisi balap dalam kode sinkron. Untuk kode async konkuren, pertimbangkan sinkronisasi tambahan.

Tantangan

Penghitung suara

Dari list suara = ['A','B','A','C','B','A'], hitung perolehan tiap kandidat dengan update + ifAbsent. Cetak map hasilnya dan pemenangnya (pakai reduce pada entries).

text
void main() {
  var suara = ['A', 'B', 'A', 'C', 'B', 'A'];
  var hasil = <String, int>{};
  // TODO: update + ifAbsent
  // TODO: pemenang = entries.reduce(...)
}

Kuis Bab

Uji pemahamanmu: Bab 3: Fungsi Lanjut & Collection

Jawab 5 soal berikut, lalu tekan "Periksa Jawaban".

1.Diberikan void sapa({String nama = 'Tamu'}), bagaimana cara memanggilnya dengan nama 'Budi'?

2.Manakah penulisan arrow function yang valid di Dart?

3.Apa output dari: var l = [1, 2, 3]; l.add(4); print(l.length);

4.Apa isi list b setelah: var a = [1, 2]; var b = [...a, 3];

5.Struktur data mana yang menyimpan pasangan kunci-nilai (key-value)?