Nullable receiver extensions in Kotlin - Time & Space Complexity
We want to understand how the time it takes to run code with nullable receiver extensions changes as the input size grows.
Specifically, how does calling an extension function on a nullable object affect performance when used repeatedly?
Analyze the time complexity of the following code snippet.
fun String?.countChars(): Int {
return this?.length ?: 0
}
fun totalChars(list: List): Int {
var sum = 0
for (item in list) {
sum += item.countChars()
}
return sum
}
This code defines an extension function on a nullable String and sums the lengths of all strings in a list, safely handling nulls.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through each element in the list and calling the nullable extension function.
- How many times: Once for each element in the list (n times).
Each element in the list causes one call to the extension function, which does a simple check and returns length or zero.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 calls to countChars() |
| 100 | About 100 calls to countChars() |
| 1000 | About 1000 calls to countChars() |
Pattern observation: The number of operations grows directly with the number of items in the list.
Time Complexity: O(n)
This means the time to run grows linearly with the number of elements in the list.
[X] Wrong: "Nullable receiver extensions add extra hidden loops or slow down the code exponentially."
[OK] Correct: The extension function runs once per element and does a simple check, so it only adds a small constant time per call, not extra loops.
Understanding how nullable extensions behave helps you write safe and efficient Kotlin code, a skill valued in many coding challenges and real projects.
What if we changed the list to a nested list of nullable strings? How would the time complexity change?