Belajar Scala - Collections & Immutable Data
Episode 6 of 23

Belajar Scala - Collections & Immutable Data

Menguasai collections Scala yang immutable secara default: List, Vector, Map, dan Set, ditambah transformasi inti map, filter, flatMap, dan fold yang menjadi pola kerja harian — plus string interpolation dan cara memilih struktur data yang tepat untuk setiap kasus.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 5 kalian mengenal type system, sekarang kita masuk ke bread-and-butter pengembangan Scala: collections. Hampir semua kode Scala — apakah itu backend API, data pipeline, atau utilitas CLI — berputar di sekitar memanipulasi kumpulan data. Dan di Scala, collections punya satu sifat pembeda: immutable secara default.

Mengapa ini penting? Karena saat kalian "mengubah" list di Scala, kalian sebenarnya membuat list baru — yang lama tetap utuh. Ini terdengar boros, tetapi justru memberi keamanan luar biasa: sebuah collection bisa dibagikan ke mana saja tanpa takut dimutasi diam-diam. Episode ini adalah investasi terbesar kalian untuk produktivitas jangka panjang.

Collections Inti

List: Urutan Seimbang

List adalah urutan elemen dengan akses dari depan yang sangat cepat dan penambahan di depan yang murah:

List dasar
val nums = List(1, 2, 3, 4)
val plus = 0 :: nums        // prepend - murah
val back = nums :+ 5        // append - lebih mahal
println(nums)               // List(1, 2, 3, 4) - asli tak berubah

Operator :: menambahkan di depan; :+ menambahkan di belakang. Untuk akses acak yang sering, List bukan pilihan terbaik.

Vector: Akses Acak Cepat

Vector menawarkan akses acak dan update yang seimbang — hampir O(log n) untuk hampir semua operasi. Ini pilihan aman untuk collection yang diakses acak:

Vector untuk akses acak
val v = Vector(10, 20, 30, 40)
println(v(2))       // 30 - akses index cepat
val v2 = v.updated(1, 99)
println(v)          // Vector(10, 20, 30, 40) - tetap utuh

Map: Pasangan Kunci-Nilai

Map menyimpan pasangan key → value:

Map dasar
val prices = Map("apel" -> 5000, "jeruk" -> 4000)
prices.get("apel")       // Some(5000) - Option!
prices.get("mangga")     // None - tidak melempar error
val withDurian = prices.updated("durian", 9000)

Perhatikan get mengembalikan Option — langsung memanfaatkan pelajaran episode 5. Tidak ada null, tidak ada KeyNotFoundException yang mengejutkan.

Set: Unik dan Cepat

Set menyimpan elemen unik:

Set untuk keunikan
val tags = Set("scala", "jvm", "scala")
println(tags)   // Set(scala, jvm) - duplikat otomatis hilang
val tags2 = tags + "fp"

Transformasi Inti

Empat fungsi ini adalah "kata kerja" utama Scala. Kuasai dan kalian bisa membaca hampir semua pipeline data.

map: Ubah Setiap Elemen

map - transformasi 1:1
val names = List("sari", "budi", "eka")
val upper = names.map(_.toUpperCase)
// List(SARI, BUDI, EKA)

map menerapkan fungsi ke setiap elemen dan mengembalikan collection baru dengan ukuran sama.

filter: Pertahankan yang Cocok

filter - seleksi
val nums = (1 to 10).toList
val evens = nums.filter(_ % 2 == 0)
// List(2, 4, 6, 8, 10)

filter mempertahankan elemen yang memenuhi predikat, membuang sisanya.

flatMap: Map + Flatten

flatMap adalah map yang hasil tiap elemennya adalah collection, lalu diratakan:

flatMap - map lalu flatten
val words = List("halo", "dunia")
val chars = words.flatMap(_.split(""))
// List(h, a, l, o, d, u, n, i, a)
 
val numbers = List(1, 2, 3)
val pairs = numbers.flatMap(n => List(n, n * 10))
// List(1, 10, 2, 20, 3, 30)

fold: Akumulasi ke Satu Nilai

foldLeft mengakumulasi elemen mulai dari nilai awal:

foldLeft - akumulasi
val nums = List(1, 2, 3, 4, 5)
val total = nums.foldLeft(0)((acc, n) => acc + n)
// 15
 
val csv = List("a", "b", "c").foldLeft("")((acc, s) => acc + s + ",")
// "a,b,c,"

foldLeft(0), foldRight, dan reduce adalah variasi dari pola yang sama. Untuk kasus umum yang "cukup jumlah", Scala menyediakan shortcut seperti .sum, .max, .min.

Rantai Transformasi

Kekuatan Scala terletak pada penggabungan transformasi — dan dengan collection immutable, rantai ini aman:

Pipeline transformasi
val transactions = List(
  ("Sari", 50.0), ("Budi", -20.0), ("Eka", 100.0), ("Sari", 30.0)
)
 
val result = transactions
  .filter(_._2 > 0)           // hanya transaksi masuk
  .map(_._1.toUpperCase)      // nama jadi huruf besar
  .distinct                   // hilangkan duplikat
  .sorted                     // urutkan
// List(BUDI, EKA, SARI)
100%

Setiap langkah menghasilkan collection baru, sehingga bisa di-test per langkah dan di-reorder tanpa efek samping.

Memilih Struktur Data

KebutuhanPilihAlasan
Urutan, prepend seringListprepend O(1)
Akses acak, ukuran besarVectorakses seimbang
Lookup key cepatMaphash-based
Keunikan elemenSetduplikat otomatis
Kinerja maksimalArrayprimitif langsung (episode 21)

Tip

Jangan terlalu memikirkan List vs Vector pada tahap ini — List adalah default yang paling idiomatis. Optimisasi struktur data baru penting saat profiling di episode 21. Yang jauh lebih penting adalah menguasai map/filter/flatMap/fold.

String dan Format

String interpolation sudah kita kenal di episode 5. Untuk format angka, Scala memakai String.format dari Java atau interpolator f:

Format angka
val price = 1234.5678
println(f"$price%.2f")          // 1234.57 - dua desimal
println(s"Harga: Rp ${price.round}") // pembulatan

Common Pitfalls

  • Mengubah collection di dalam loop — hindari pola var buf = ...; for (...) buf += .... Pakai transformasi.
  • :+ pada List besar — append di List itu O(n); jika kalian sering append, pakai Vector atau prepend lalu reverse.
  • .get langsung pada Mapmap("kunci") melempar NoSuchElementException jika kunci tak ada; pakai .get (Option) atau .getOrElse:
    getOrElse yang aman
    val p = prices.getOrElse("mangga", 0)
  • Memutasi collection bersama — jangan berbagi var collection antar thread; gunakan collection immutable (episode 12).

Penutup

Inti yang harus dibawa pulang:

  • List, Vector, Map, Set semuanya immutable secara default.
  • Empat kata kerja utama: map, filter, flatMap, fold.
  • Rantai transformasi aman dan mudah diuji karena setiap langkah membuat nilai baru.
  • Pilih struktur data sesuai pola akses: List untuk prepend, Vector untuk akses acak, Map untuk look-up, Set untuk keunikan.
  • Map.get mengembalikan Option — tidak ada kejutan null.

Di episode 7 selanjutnya, kita menggabungkan type system dan collections lewat pattern matching dan ADTmatch expressions dengan wildcard dan guards, destructuring, dan modeling domain dengan enum + case class. Sampai jumpa di episode 7!

Belajar Scala - Collections & Immutable Data | Belajar Scala