Kotlin in Keyword
last modified April 19, 2025
Kotlin's in keyword is a versatile operator used for range checking
and iteration. It simplifies collection operations and range comparisons. This
tutorial explores the in keyword in depth with practical examples.
Basic Definitions
The in keyword in Kotlin serves two main purposes. First, it checks
if a value is within a range or collection. Second, it enables iteration over
collections or ranges. The operator is overloadable via the contains
function.
Range Checking with in
The simplest use of in checks if a value falls within a specified
range. This works with numeric ranges, character ranges, and custom ranges.
package com.zetcode
fun main() {
val x = 5
if (x in 1..10) {
println("$x is between 1 and 10")
}
val grade = 'B'
if (grade in 'A'..'D') {
println("$grade is a passing grade")
}
}
Here we check if a number is within 1-10 range and if a character is between A-D.
The in operator makes these checks concise and readable. Both
conditions evaluate to true in these examples.
Collection Membership Check
The in operator can check if an element exists in a collection. This
works with lists, sets, arrays, and other collection types.
package com.zetcode
fun main() {
val colors = listOf("red", "green", "blue")
if ("green" in colors) {
println("Green is in the list")
}
val numbers = setOf(1, 2, 3, 5, 8)
println(4 in numbers) // Output: false
}
We check if "green" exists in a list of colors and if 4 exists in a set of
numbers. The first check returns true while the second returns false. The
in operator calls the contains method internally.
Iteration with in
The in keyword enables iteration over ranges and collections in
for loops. This provides a clean syntax for looping operations.
package com.zetcode
fun main() {
for (i in 1..5) {
print("$i ") // Output: 1 2 3 4 5
}
println()
val fruits = listOf("apple", "banana", "cherry")
for (fruit in fruits) {
print("$fruit ") // Output: apple banana cherry
}
}
The first loop iterates over a numeric range from 1 to 5. The second loop
iterates through a list of fruits. The in keyword makes these loops
concise and easy to understand.
Custom in Operator
You can define custom behavior for the in operator by implementing
the contains function in your classes. This enables range-like
operations on custom types.
package com.zetcode
class Week(val days: List<String>) {
operator fun contains(day: String) = day in days
}
fun main() {
val week = Week(listOf("Mon", "Tue", "Wed", "Thu", "Fri"))
println("Wed" in week) // Output: true
println("Sun" in week) // Output: false
}
Here we create a Week class that implements contains.
This allows us to use in to check if a day is in the week. The
operator provides a natural syntax for this membership check.
Not in Operator
Kotlin also provides the !in operator to check if a value is not in
a range or collection. This is the logical inverse of the in
operator.
package com.zetcode
fun main() {
val primes = setOf(2, 3, 5, 7, 11)
val num = 4
if (num !in primes) {
println("$num is not prime")
}
val validChars = 'a'..'z'
println('$' !in validChars) // Output: true
}
We check if 4 is not in a set of prime numbers and if '$' is not in the range of
valid lowercase letters. Both conditions evaluate to true. The !in
operator improves code readability for negative checks.
String Contains Check
The in operator can check if a substring exists within a string.
This provides a concise alternative to the contains method.
package com.zetcode
fun main() {
val message = "Hello Kotlin"
if ("Kot" in message) {
println("Substring found")
}
val forbidden = listOf("spam", "ads", "virus")
val email = "Buy cheap ads now!"
if (forbidden.any { it in email }) {
println("Spam detected")
}
}
We check if "Kot" exists in a string and if any forbidden words appear in an
email. The in operator makes these checks straightforward. The
second example combines in with any for more complex
checks.
Map Key Check
The in operator can check if a key exists in a map. This provides a
clean way to verify map membership without explicitly calling methods.
package com.zetcode
fun main() {
val capitals = mapOf(
"USA" to "Washington",
"UK" to "London",
"France" to "Paris"
)
if ("France" in capitals) {
println("Capital of France is ${capitals["France"]}")
}
println("Germany" in capitals) // Output: false
}
We check if "France" and "Germany" are keys in a map of capitals. The
in operator makes these checks concise. When checking map keys,
in is more readable than calling containsKey.
Best Practices for in Operator
- Prefer in for readability: Use
ininstead ofcontainswhen possible for cleaner code. - Combine with ranges: Leverage
inwith range expressions for concise boundary checks. - Implement contains: For custom types, implement
containsto enableinoperator support. - Use !in for negative checks: The
!inoperator provides clear syntax for absence checks. - Consider performance: For large collections, be aware that
inmay have O(n) complexity unless using a Set.
Source
Kotlin Operator Overloading Documentation
This tutorial covered Kotlin's in keyword in depth, showing its use
for range checking, collection membership, and iteration. We explored various
scenarios including custom implementations and string operations. The
in operator provides concise and readable syntax for common
operations.
Author
List all Kotlin tutorials.