Counting entries
The number of key-value pairs in a map is its size. In Kotlin, size is a property, so you write it without parentheses:
val scores = mutableMapOf<String, Int>()
scores["Alice"] = 95
scores["Bob"] = 87
scores["Charlie"] = 72
val count = scores.size
println(count) // 3
Writing scores.size(), as you would in some other languages, does not compile in Kotlin. It treats size as a value and then tries to call that value like a function.
The size counts entries, not keys and values separately. Three pairs give a size of 3, not 6.
An empty map
A new map with no entries has a size of 0. To test for that case, use isEmpty(), which is a function and does have parentheses, or its opposite, isNotEmpty():
println(scores.isEmpty()) // false
val empty = mutableMapOf<String, Int>()
println(empty.size) // 0
println(empty.isEmpty()) // true
The difference between a property and a function is easy to mix up. A good rule is that size describes something the map has, and isEmpty() asks it a question. Your editor will remind you, because the compiler rejects the wrong form.
How the size changes
The size follows the contents of the map, so it changes when you add or remove entries, and it stays the same when you update one:
- Adding a new key makes the size one larger.
- Assigning to an existing key replaces its value, and the size does not change. This is true even when you assign the same value again.
- Removing a key with
remove("Alice")makes the size one smaller. Removing a key that is not there changes nothing.
val ages = mutableMapOf("Alice" to 25)
ages["Bob"] = 30
println(ages.size) // 2
ages["Alice"] = 26
println(ages.size) // 2
ages.remove("Bob")
println(ages.size) // 1
Because each key appears only once, the size is also the number of different keys. If you build a map from a list of words and count each word, the final size tells you how many distinct words there were.
Counting distinct values
Here a loop counts how many times each word appears in a list. The map ends up with one entry per distinct word, so its size is the number of different words:
val words = listOf("red", "blue", "red", "green", "blue", "red")
val counts = mutableMapOf<String, Int>()
for (w in words) {
counts[w] = (counts[w] ?: 0) + 1
}
println(counts) // {red=3, blue=2, green=1}
println(counts.size) // 3
The list has six items but the map has only three, because repeated words update an existing entry instead of adding a new one.
Using the size in conditions
Because size is a plain integer, you can compare it like any other number:
if (scores.size > 2) {
println("more than two")
}
The same word, size, is also how you count the items of a list or an array: listOf(1, 2).size is 2. A string is the exception, since it uses length.
The exercise
The starting code has a map of three scores:
val scores = mutableMapOf("Alice" to 95, "Bob" to 87, "Charlie" to 72)
The task is to store the number of entries in a new variable named count. Declare a val with that name, and give it scores.size:
val scores = mutableMapOf("Alice" to 95, "Bob" to 87, "Charlie" to 72)
val count = scores.size
The value of count is 3. Note that count is a snapshot: it is a plain integer, so if you add entries to scores later, count stays 3. Read scores.size again when you need the current number.
Reading size costs nothing, however large the map is, because the map keeps its own count. You do not need to store the number yourself.
Common mistakes
- Adding parentheses.
scores.size()does not compile. Usescores.size. - Using
length. Strings havelength, but maps and lists usesize. - Expecting a stored count to update. A variable that was assigned
scores.sizekeeps the number it received at that moment. - Forgetting that updates do not change the size. Assigning to an existing key replaces a value, and the size stays the same.
Key takeaways
map.sizeis the number of key-value pairs, written without parentheses.isEmpty()andisNotEmpty()test for an empty map.- Adding a new key grows the map, removing a key shrinks it, and updating a key leaves the size alone.