Counting entries
The number of key-value pairs in a Scala Map is its size. It is a method without parentheses, written after the map's name:
val ages = Map("Ana" -> 12, "Ben" -> 15)
println(ages.size) // 2
It counts pairs, not keys and values separately, so the two-entry map above has size 2, not 4. The result is an Int.
The exercise
The starting code has a mutable map of three scores. The task is to store its size in a val named count.
- Declare
val count. - Assign
scores.size.
val scores = scala.collection.mutable.Map("Alice" -> 95, "Bob" -> 87, "Charlie" -> 72)
val count = scores.size
Here count is 3.
How the size changes
For a mutable map, size follows the contents. Adding a key with a new name increases it, and replacing the value of an existing key does not:
val scores = scala.collection.mutable.Map("Alice" -> 95, "Bob" -> 87, "Charlie" -> 72)
println(scores.size) // 3
scores("Alice") = 99 // existing key: size unchanged
println(scores.size) // 3
scores("Dan") = 50 // new key: size grows
println(scores.size) // 4
scores -= "Bob" // remove an entry
println(scores.size) // 3
Remember that count in the exercise is a snapshot. It holds the number 3 and doesn't update if the map changes later.
Because size is read straight from the map, you can use it inside expressions: scores.size > 2 is a Boolean, and scores.size - 1 is an Int like any other.
Size, isEmpty and nonEmpty
To test whether a map has any entries, use isEmpty or nonEmpty instead of comparing the size yourself. An empty map has size 0:
val empty = Map[String, Int]()
println(empty.size) // 0
println(empty.isEmpty) // true
println(empty.nonEmpty) // false
Why size is useful
The size answers questions such as "how many students are in the table?" without looping. It is also the quick way to check your work: after adding three entries to an empty map the size should be 3, and if it isn't, a key was repeated and overwrote an earlier entry. Checking the size after building a map from data is a cheap way to catch duplicate keys.
The same call works on both kinds of map. For an immutable Map the size is fixed for the lifetime of that map value, and an "updated" copy has its own size.
For instance, val a = Map("x" -> 1) has size 1, and val b = a.updated("y", 2) creates a separate map: a keeps size 1 and b has size 2.
Counting some of the entries
size counts everything. To count only the entries that satisfy a condition, use count with a function that receives each (key, value) pair; _._2 picks the value out of the pair:
val scores = scala.collection.mutable.Map("Alice" -> 95, "Bob" -> 87, "Charlie" -> 72)
println(scores.count(_._2 > 80)) // 2
Other collections report their length the same way: size works on arrays, lists and strings too, and arrays, lists and strings also have length. Only maps lack length.
Common mistakes
- Using
length. Arrays and lists havelength, but a map's method issize.scores.lengthdoesn't compile. - Writing
scores.size(). Calling it with empty parentheses fails to compile for a map, becausesizeis defined without a parameter list. Writescores.size. - Expecting duplicate keys to count twice. Keys are unique, so
Map("a" -> 1, "a" -> 2).sizeis1. - Mixing up size and the last key. A map has no positions, so there is no "last index" to compute from the size.
Key takeaways
map.sizeis the number of key-value pairs.- Replacing a value keeps the size; adding a new key grows it; removing a key shrinks it.
- Use
isEmptyandnonEmptyto check for entries.
