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:

EkspresiFunction yang dipanggilMengembalikan
x in 1..10IntRange.contains(x)Boolean
x !in 1..10!IntRange.contains(x)Boolean
item in listList.contains(item)Boolean
item !in set!Set.contains(item)Boolean
key in mapMap.containsKey(key)Boolean
char in stringString.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 #

kotlin
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:

text
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: true

Mari kita uraikan bagian-bagian penting pada contoh di atas:

  1. nilai in 1..10 memanggil IntRange.contains(7), yang mengembalikan true karena 7 berada dalam rentang inklusif 1..10. Pemeriksaan rentang sangat efisien: hanya dua pembandingan, tidak peduli seberapa besar rentangnya.
  2. nilai !in 1..5 menghasilkan true karena 7 berada di luar rentang 1..5. Negasi !in setara dengan !(nilai in 1..5).
  3. "mangga" in buah memanggil List.contains("mangga"), yang melakukan iterasi linier O(n) sampai menemukan kecocokan. Untuk list besar, pertimbangkan Set agar pemeriksaan menjadi O(1).
  4. "kopi" in stok memeriksa apakah "kopi" adalah key pada Map. Tidak ada pemeriksaan terhadap value (12, 5, 8).
  5. 'a' in teks memeriksa apakah Char 'a' muncul di dalam string "Halo". Operasi ini memanggil String.contains(char) yang melakukan pencarian linier pada karakter string.
  6. for (huruf in 'a'..'e') mengiterasi CharRange. Di dalam loop, huruf in "abcdef" memeriksa setiap huruf satu per satu. Kombinasi rentang dan pemeriksaan keanggotaan sering muncul pada algoritma pemrosesan teks.
  7. "IT" in divisi memeriksa keanggotaan dalam Set. Implementasi Set default (berbasis LinkedHashSet) menjamin pemeriksaan O(1) rata-rata, jauh lebih cepat dari List untuk 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:

kotlin Contoh: mendefinisikan operator in sendiri
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) // true

Efisiensi 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.

kotlin Contoh: konversi ke Set untuk efisiensi
val blacklist = listOf("spam", "phishing", "malware").toSet()
if (email in blacklist) {
    // pemeriksaan O(1)
}

Referensi Lanjutan #

  • Control flow — bagian in dan !in pada panduan control flow resmi
  • Ranges — pemakaian in untuk 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.