Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sets & Maps

A map is an associative container for values. Rather than indexing values by their position in a sequence, as is the case for arrays and lists, a map associates each value with a key. This key is then used to look up the corresponding value. Keys must therefore be unique.

A set is a little like a map with keys but no associated values. In effect, the keys are the values we wish to store! Sets are essentially unordered collections in which items are guaranteed not to be duplicated.

C has no equivalents to sets and maps in its standard library, but Python provides both of these data structures. (A Python dictionary is equivalent to a Kotlin map.)

Creation

Sets and maps are created in a similar way to arrays and lists, by invoking the constructors for Set<> and Map<>, or the creation functions setOf() and mapOf(). The latter is often used in conjunction with the to() function, to construct maps in a very readable way.

val fixedOptions = setOf("Save", "Load", "Quit")

val fixedPrices = mapOf(
    "Apple" to 32,
    "Orange" to 55,
    "Kiwi" to 20
)

The same mutability considerations that apply to lists also apply to sets and maps. Thus the Set<> constructor and setOf() will give you an immutable set, whereas the Map<> constructor and mapOf() will give you an immutable map.

If you want mutability, you must request it explicitly:

val options = mutableSetOf("Save", "Load", "Quit")

val prices = mutableMapOf<String,Int>()   // key & value types needed!

As with mutable lists, it is necessary to specify the type(s) of the collection’s contents when creating an empty mutable set or an empty mutable map.

Set Manipulation

To add an item to or remove an item from a mutable set, use the add() or remove() method, as appropriate.

These methods expect a single argument: the item to be added/removed. Both of them return true if the operation succeeded, false if it did not.

val names = mutableSetOf("Joe", "Sarah", "Nicole")

print("Enter your name: ")
val name = readln()

if (names.add(name)) {
    println("$name added")
}
else {
    println("I'm sorry, we already have a $name")
}

If you want to add or remove multiple items at the same time, you can use addAll() or removeAll(). Both of these methods accept a collection of the values to be added or removed as the only argument. Both return true if at least one value was added or removed, or false if there was no modification of the set.

You can empty a mutable set of all its contents using the clear() method.

Looking Up Values in a Map

You can look up the value associated with a key using the [] operator or the get() method:

val prices = mutableMapOf(
    "Apple" to 32,
    "Orange" to 55,
    "Kiwi" to 20
)

println(prices["Apple"])   // prints 32
println(prices["Pear"])    // ?

Question

What do you think happens when the second of these two print statements is executed?

If you are unsure, try running this code

Answer

The statement executes as normal, printing the value null

It’s important to understand that the object returned when [] or get() is used on a map is an instance of a nullable type, which we will cover later.

If you don’t want this behaviour, you can use getOrElse() instead:

prices.getOrElse(item) { 15 }

prices.getOrElse(item) {
    throw NoSuchElementException("No price for $item")
}

As its name suggests, this returns the associated value if the given key is present, or else it performs the action specified by the given lambda expression. In the first of the examples above, this lambda expression simply returns a default value. The second example throws an exception in cases where the key is missing.

Modifying a Map

You can modify an existing value or add a new key-value pair to a mutable map using the [] operator in an assignment operation, or by calling the put() method. For example, given the mutable map described earlier, you could do this:

prices["Apple"] = 40    // updates price of Apple
prices["Banana"] = 65   // introduces new item & price

You can remove a key-value pair from a mutable map by invoking the remove() method on it, with the key as the argument.

You can empty a mutable map of all its contents using the clear() method.