Operator in dan !in adalah cara ergonomis untuk memeriksa apakah suatu nilai terdapat dalam rentang, koleksi, atau struktur lain yang dapat diiterasi. Operator ini mengembalikan Boolean, sehingga sering dipakai di kondisi if atau when. Yang menarik, operator ini sebenarnya memanggil function contains(), sehingga kita dapat mendefinisikan perilaku keanggotaan khusus pada class buatan sendiri. Pada chapter ini kita akan membahas penggunaan in dan !in pada rentang, list, set, map, dan string, lalu cara kerjanya melalui konvensi contains().
Dasar Penggunaan #
Operator in adalah pemanggilan function contains(). Ekspresi x in list dipetakan ke list.contains(x). Operator !in adalah negasinya, dipetakan ke !list.contains(x). Berikut ringkasan konteks penggunaan:
| Ekspresi | Function yang dipanggil | Mengembalikan |
|---|---|---|
x in 1..10 | IntRange.contains(x) | Boolean |
x !in 1..10 | !IntRange.contains(x) | Boolean |
item in list | List.contains(item) | Boolean |
item !in set | !Set.contains(item) | Boolean |
key in map | Map.containsKey(key) | Boolean |
char in string | String.contains(char) | Boolean |
Perhatikan bahwa pada Map, operator in memeriksa key, bukan value. Untuk memeriksa value, gunakan map.containsValue(v) secara eksplisit karena tidak ada operator simbol yang setara.
Pemeriksaan pada Berbagai Tipe #
fun main() {
val nilai = 7
println("nilai in 1..10: ${nilai in 1..10}")
println("nilai !in 1..10: ${nilai !in 1..10}")
println("nilai !in 1..5: ${nilai !in 1..5}")
val buah = listOf("apel", "mangga", "jeruk")
println("'mangga' in buah: ${"mangga" in buah}")
println("'anggur' !in buah: ${"anggur" !in buah}")
val stok = mapOf(
"kopi" to 12,
"gula" to 5,
"susu" to 8
)
println("'kopi' in stok: ${"kopi" in stok}")
println("'teh' in stok: ${"teh" in stok}")
val teks = "Halo"
println("'a' in teks: ${'a' in teks}")
println("'z' !in teks: ${'z' !in teks}")
for (huruf in 'a'..'e') {
val ada = huruf in "abcdef"
println("'$huruf' ada di \"abcdef\": $ada")
}
val divisi = setOf("IT", "HR", "Keu")
println("'IT' in divisi: ${"IT" in divisi}")
println("'Marketing' !in divisi: ${"Marketing" !in divisi}")
}Output yang Dihasilkan:
nilai in 1..10: true
nilai !in 1..10: false
nilai !in 1..5: true
'mangga' in buah: true
'anggur' !in buah: true
'kopi' in stok: true
'teh' in stok: false
'a' in teks: true
'z' !in teks: true
'a' ada di "abcdef": true
'b' ada di "abcdef": true
'c' ada di "abcdef": true
'd' ada di "abcdef": true
'e' ada di "abcdef": true
'IT' in divisi: true
'Marketing' !in divisi: trueMari kita uraikan bagian-bagian penting pada contoh di atas:
nilai in 1..10memanggilIntRange.contains(7), yang mengembalikantruekarena7berada dalam rentang inklusif1..10. Pemeriksaan rentang sangat efisien: hanya dua pembandingan, tidak peduli seberapa besar rentangnya.nilai !in 1..5menghasilkantruekarena7berada di luar rentang1..5. Negasi!insetara dengan!(nilai in 1..5)."mangga" in buahmemanggilList.contains("mangga"), yang melakukan iterasi linierO(n)sampai menemukan kecocokan. Untuk list besar, pertimbangkanSetagar pemeriksaan menjadiO(1)."kopi" in stokmemeriksa apakah"kopi"adalah key padaMap. Tidak ada pemeriksaan terhadap value (12,5,8).'a' in teksmemeriksa apakahChar'a'muncul di dalam string"Halo". Operasi ini memanggilString.contains(char)yang melakukan pencarian linier pada karakter string.for (huruf in 'a'..'e')mengiterasiCharRange. Di dalam loop,huruf in "abcdef"memeriksa setiap huruf satu per satu. Kombinasi rentang dan pemeriksaan keanggotaan sering muncul pada algoritma pemrosesan teks."IT" in divisimemeriksa keanggotaan dalamSet. ImplementasiSetdefault (berbasisLinkedHashSet) menjamin pemeriksaanO(1)rata-rata, jauh lebih cepat dariListuntuk koleksi besar.
Cara Kerja Konvensi contains #
Operator in bekerja melalui konvensi function contains(). Class atau tipe yang ingin mendukung operator in cukup mengimplementasikan function contains(element: T): Boolean dengan modifier operator. Berikut contoh sederhana:
class Kategori(val item: List<String>) {
operator fun contains(nama: String): Boolean =
nama in item
}
val k = Kategori(listOf("elektronik", "fashion"))
println("elektronik" in k) // trueEfisiensi Pemeriksaan #
Pilihan tipe koleksi memengaruhi kinerja operator in. Pada List, pemeriksaan bersifat O(n) linier. Pada Set, pemeriksaan rata-rata O(1) berbasis hash table. Pada Map, pemeriksaan key juga O(1) rata-rata. Untuk data dengan banyak pemeriksaan keanggotaan, konversi ke Set sekali di awal dapat mempercepat eksekusi secara signifikan.
val blacklist = listOf("spam", "phishing", "malware").toSet()
if (email in blacklist) {
// pemeriksaan O(1)
}Referensi Lanjutan #
- Control flow
— bagian
indan!inpada panduan control flow resmi - Ranges
— pemakaian
inuntuk pengujian keanggotaan range
Dengan memahami cara kerja in dan !in beserta konvensi contains(), kita siap mengenal operator pemeriksaan tipe is dan !is yang memicu smart cast pada chapter berikutnya.