Kotlin !in Keyword
last modified April 19, 2025
Kotlin's `!in` operator checks for the absence of an element in a collection or range. It is the negation of the `in` operator. This tutorial explores the `!in` keyword in depth with practical examples.
Basic Definitions
The `!in` keyword in Kotlin is a negation operator that checks if an element is not present in a collection or range. It returns true when the element is absent and false when present. It works with all types that support the `in` operator.
Checking Absence in Lists
The most common use of `!in` is to check if an element is not in a list. This is more readable than writing `!(element in list)`. The example shows basic usage with a list of strings.
package com.zetcode fun main() { val colors = listOf("red", "green", "blue") val color = "yellow" if (color !in colors) { println("$color is not in the list") } }
Here we check if "yellow" is not in the colors list. Since it's absent, the condition evaluates to true and the message is printed. This is clearer than negating the `in` check.
Checking Absence in Ranges
The `!in` operator works with ranges to check if a value is outside the range. This is useful for validating input values or checking boundary conditions. The example demonstrates numeric range checking.
package com.zetcode fun main() { val validRange = 1..100 val value = 105 if (value !in validRange) { println("$value is out of valid range") } }
We check if 105 is outside the 1..100 range. Since it is, the condition is true and the message prints. This is more concise than writing `!(value in validRange)`.
Checking Absence in Maps
With maps, `!in` checks for the absence of a key. This is useful when you want to avoid overwriting existing entries. The example shows key absence checking.
package com.zetcode fun main() { val capitals = mapOf( "France" to "Paris", "Germany" to "Berlin" ) val country = "Spain" if (country !in capitals) { println("$country is not in the map") } }
We check if "Spain" is not a key in the capitals map. Since it's absent, the message prints. Note that `!in` checks keys, not values, in map collections.
Checking Absence in Strings
The `!in` operator can check if a character is not present in a string. This is useful for input validation or text processing. The example demonstrates character checking.
package com.zetcode fun main() { val vowels = "aeiou" val letter = 'z' if (letter !in vowels) { println("$letter is not a vowel") } }
We check if 'z' is not in the vowels string. Since it's absent, the message prints. This is a clean way to check for excluded characters in input validation.
Custom Classes with !in
For custom classes to work with `!in`, they must implement the `contains()` function. The example shows a custom range class that supports `!in` checks.
package com.zetcode class TemperatureRange(val min: Int, val max: Int) { operator fun contains(temp: Int) = temp in min..max } fun main() { val validTemps = TemperatureRange(10, 30) val currentTemp = 35 if (currentTemp !in validTemps) { println("$currentTemp°C is dangerous") } }
The TemperatureRange class implements `contains()` to support `in` and `!in`. We check if 35°C is outside the valid range. Since it is, the warning message prints. This shows how to extend `!in` to custom types.
!in with when Expressions
The `!in` operator works well with Kotlin's `when` expressions for concise conditional logic. The example demonstrates using `!in` in a when expression.
package com.zetcode fun main() { val forbidden = setOf("admin", "root", "system") val username = "guest" when (username) { !in forbidden -> println("Access granted") else -> println("Access denied") } }
We check if "guest" is not in the forbidden usernames set. Since it's absent, the "Access granted" message prints. This shows how `!in` can simplify when expressions for exclusion checks.
!in with Smart Casts
Combining `!in` with smart casts allows for powerful type-safe checks. The example shows how to exclude certain types from processing using `!in`.
package com.zetcode fun process(value: Any) { if (value !in listOf(1, 2, 3)) { println("Processing $value") } } fun main() { process(4) // Output: Processing 4 process(2) // No output }
The function processes values that aren't 1, 2, or 3. The `!in` check combined with smart casting makes this exclusion clear and concise. This pattern is useful for filtering inputs.
Best Practices for !in Operator
- Prefer !in over negation: Use `!in` instead of `!(x in y)` for better readability.
- Use with meaningful names: Name collections/ranges clearly to make `!in` checks self-documenting.
- Combine with when: `!in` works well in when expressions for exclusion patterns.
- Consider performance: For large collections, be aware that `!in` performs a linear search in lists.
- Extend carefully: Only implement `contains()` for custom classes when `in`/`!in` semantics make sense.
Source
Kotlin Operator Overloading Documentation
This tutorial covered Kotlin's `!in` keyword in depth, showing how to check for absence in collections, ranges, and custom types. We explored various scenarios including strings, maps, and smart casts. Proper use of `!in` can make your exclusion checks more readable and expressive.
Author
List all Kotlin tutorials.