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.

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.
List adalah urutan elemen dengan akses dari depan yang sangat cepat dan penambahan di depan yang murah:
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 berubahOperator :: menambahkan di depan; :+ menambahkan di belakang. Untuk akses acak yang sering, List bukan pilihan terbaik.
Vector menawarkan akses acak dan update yang seimbang — hampir O(log n) untuk hampir semua operasi. Ini pilihan aman untuk collection yang diakses 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 utuhMap menyimpan pasangan key → value:
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 menyimpan elemen unik:
val tags = Set("scala", "jvm", "scala")
println(tags) // Set(scala, jvm) - duplikat otomatis hilang
val tags2 = tags + "fp"Empat fungsi ini adalah "kata kerja" utama Scala. Kuasai dan kalian bisa membaca hampir semua pipeline data.
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.
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 adalah map yang hasil tiap elemennya adalah collection, lalu diratakan:
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)foldLeft mengakumulasi elemen mulai dari nilai awal:
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.
Kekuatan Scala terletak pada penggabungan transformasi — dan dengan collection immutable, rantai ini aman:
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)Setiap langkah menghasilkan collection baru, sehingga bisa di-test per langkah dan di-reorder tanpa efek samping.
| Kebutuhan | Pilih | Alasan |
|---|---|---|
| Urutan, prepend sering | List | prepend O(1) |
| Akses acak, ukuran besar | Vector | akses seimbang |
| Lookup key cepat | Map | hash-based |
| Keunikan elemen | Set | duplikat otomatis |
| Kinerja maksimal | Array | primitif 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 interpolation sudah kita kenal di episode 5. Untuk format angka, Scala memakai String.format dari Java atau interpolator f:
val price = 1234.5678
println(f"$price%.2f") // 1234.57 - dua desimal
println(s"Harga: Rp ${price.round}") // pembulatanvar 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 Map — map("kunci") melempar NoSuchElementException jika kunci tak ada; pakai .get (Option) atau .getOrElse:
val p = prices.getOrElse("mangga", 0)var collection antar thread; gunakan collection immutable (episode 12).Inti yang harus dibawa pulang:
List, Vector, Map, Set semuanya immutable secara default.map, filter, flatMap, fold.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 ADT — match expressions dengan wildcard dan guards, destructuring, dan modeling domain dengan enum + case class. Sampai jumpa di episode 7!