Set read-only hanya bisa dibaca; kita tidak bisa menambah atau menghapus elemen setelah dibuat. Ketika koleksi unik perlu diubah seiring waktu — misalnya tag yang dipilih pengguna, ID peserta yang bergabung dan keluar — kita menggunakan MutableSet<T>. Pada chapter ini kita akan mempraktikkan operasi mutasi MutableSet dan memahami perbedaan dua implementasi di baliknya: LinkedHashSet dan HashSet.
Membuat MutableSet #
MutableSet dibuat menggunakan mutableSetOf(...). Pustaka standar Kotlin memilih LinkedHashSet sebagai implementasi default, sehingga urutan penyisipan elemen tetap dipertahankan.
val tag: MutableSet<String> = mutableSetOf("kotlin", "jvm", "android")
val angka = mutableSetOf(1, 2, 3) // MutableSet<Int>
val kosong: MutableSet<Int> = mutableSetOf()Operasi Mutasi #
| Metode | efek | Catatan |
|---|---|---|
add(x) | menambah x jika belum ada | Mengembalikan true jika x benar-benar ditambahkan |
remove(x) | menghapus x jika ada | Mengembalikan true jika berhasil |
addAll(c) | menambah semua elemen dari collection c | Duplikat diabaikan |
removeAll(c) | menghapus semua elemen yang ada di c | Mengembalikan true jika ada perubahan |
retainAll(c) | menyisakan hanya elemen yang ada di c | Irisan in-place |
clear() | mengosongkan set | size menjadi 0 |
LinkedHashSet vs HashSet #
Dua implementasi MutableSet di JVM memiliki karakteristik urutan yang berbeda:
| Implementasi | Cara membuat | Urutan | Performa add/contains |
|---|---|---|---|
LinkedHashSet | mutableSetOf, linkedSetOf | Urutan penyisipan dipertahankan | Sedikit lebih lambat (menyimpan daftar tertaut) |
HashSet | hashSetOf | Tidak menjamin urutan, berdasarkan hash code | Paling cepat |
TreeSet (sorted) | sortedSetOf | Urutan natural atau via Comparator | O(log n) |
Contoh Lengkap #
import java.util.LinkedHashSet
fun main() {
// MutableSet default = LinkedHashSet (urutan penyisipan dipertahankan)
val tagMutable = mutableSetOf("kotlin", "jvm", "android")
println("Awal: $tagMutable")
// add dan remove
tagMutable.add("backend")
println("Setelah add backend: $tagMutable")
tagMutable.add("kotlin") // sudah ada, tidak ada perubahan
println("Setelah add kotlin (duplikat): $tagMutable")
tagMutable.remove("jvm")
println("Setelah remove jvm: $tagMutable")
// addAll dan removeAll
tagMutable.addAll(listOf("web", "mobile", "kotlin"))
println("Setelah addAll: $tagMutable")
tagMutable.removeAll(listOf("web", "mobile"))
println("Setelah removeAll: $tagMutable")
// retainAll: menyisakan hanya elemen yang ada di argumen
val angka = mutableSetOf(1, 2, 3, 4, 5)
angka.retainAll(listOf(2, 4, 6, 8))
println("Setelah retainAll {2,4,6,8}: ${angka.sorted()}")
// clear
val sementara = mutableSetOf("x", "y")
sementara.clear()
println("Sementara setelah clear: $sementara, isEmpty=${sementara.isEmpty()}")
// Perbandingan: LinkedHashSet vs HashSet (urutan)
val linked: LinkedHashSet<String> = linkedSetOf("zebra", "apel", "mangga")
println("LinkedHashSet urutan: $linked")
val hashed: MutableSet<String> = hashSetOf("zebra", "apel", "mangga")
println("HashSet urutan (hash-based): ${hashed.sorted()}")
// addAll ke HashSet dengan elemen bertambah
hashed.add("banana")
println("HashSet setelah add banana: ${hashed.sorted()}")
// Konversi ke list untuk akses indeks
val daftarTag = tagMutable.toList()
println("Sebagai list indeks 0: ${daftarTag[0]}")
}Output yang Dihasilkan:
Awal: [kotlin, jvm, android]
Setelah add backend: [kotlin, jvm, android, backend]
Setelah add kotlin (duplikat): [kotlin, jvm, android, backend]
Setelah remove jvm: [kotlin, android, backend]
Setelah addAll: [kotlin, android, backend, web, mobile]
Setelah removeAll: [kotlin, android, backend]
Setelah retainAll {2,4,6,8}: [2, 4]
Sementara setelah clear: [], isEmpty=true
LinkedHashSet urutan: [zebra, apel, mangga]
HashSet urutan (hash-based): [apel, mangga, zebra]
HashSet setelah add banana: [apel, banana, mangga, zebra]
Sebagai list indeks 0: kotlinMari kita bedah baris-baris penting di atas:
tagMutable.add("kotlin"): pemanggilan ini tidak menambah elemen karena"kotlin"sudah ada.addmengembalikanfalsedansizetetap sama. Perilaku ini berbeda dariMutableList.addyang selalu menambah elemen.tagMutable.removeAll(listOf("web", "mobile")): menghapus elemen apa pun yang juga ada di argumen. Hasilnya adalahtagMutablehanya berisi elemen yang bukan anggota list.angka.retainAll(listOf(2, 4, 6, 8)): mempertahankan elemen yang ada di kedua koleksi. Hanya2dan4yang tersisa karena6dan8tidak ada di set awal.linked: LinkedHashSet<String>: urutan[zebra, apel, mangga]dipertahankan persis seperti urutan penyisipan.hashed.sorted():HashSettidak menjamin urutan, sehingga kita memanggilsorted()agar output konsisten lintas platform dan versi JVM.
Referensi Lanjutan #
- Set
— panduan resmi
MutableSet<T>danHashSet - Set API reference
— API reference
kotlin.collections.Set - Collection write operations
— panduan
add,removepadaMutableSet
Setelah memahami Set dan MutableSet, kita akan melangkah ke struktur pasangan key-value: Map.