Lists, sets and maps

Kotlin · Essentials · 10 min

Collections hold almost all program data; Kotlin's read-only vs mutable split prevents accidental changes.

Kotlin distinguishes read-only collection interfaces from mutable ones:

  • listOf(1, 2, 3) gives a List<Int>: you can read but not add. mutableListOf() gives a MutableList with add, remove, set, clear.
  • setOf / mutableSetOf hold unique elements (insertion-ordered by default, backed by LinkedHashSet).
  • mapOf("a" to 1) / mutableMapOf() hold key-value pairs (insertion-ordered LinkedHashMap).

Read-only does not mean immutable: a List reference may point to a mutable list someone else changes. It means you can't change it through that reference, which is usually what APIs should expose.

Access:

  • Lists: list[0], list.getOrNull(5), first(), last(), size, indexOf, contains or x in list.
  • Maps: map["a"] returns V? (null when missing), getValue("a") throws if missing, getOrDefault, map["b"] = 2 on mutable maps, getOrPut(key) { default }.
  • Iterate with for (x in list) and for ((k, v) in map).

Operators: list + 4 and list - 1 create new lists; += on a MutableList adds in place.

Arrays (arrayOf, intArrayOf) exist mainly for Java interop and performance; prefer lists in everyday code. emptyList(), List(5) { it * it } and buildList { add(1) } are handy builders.

Example

fun main() {
    val nums = listOf(3, 1, 2)
    // nums.add(4)                     // compile error: List is read-only
    println(nums[0] + nums.last())     // 5
    println(nums.getOrNull(10))        // null
    println(2 in nums)                 // true

    val todo = mutableListOf("write")
    todo += "test"
    todo.add(0, "plan")
    println(todo)                      // [plan, write, test]

    val tags = mutableSetOf("kotlin", "jvm")
    println(tags.add("kotlin"))        // false: already present

    val ages = mutableMapOf("Ada" to 36)
    ages["Linus"] = 28
    println(ages["Grace"])             // null
    println(ages.getOrPut("Grace") { 85 }) // 85
    for ((name, age) in ages) print("$name=$age ") // Ada=36 Linus=28 Grace=85
    println()
    println(List(4) { it * it })       // [0, 1, 4, 9]
}

Remember

  • listOf/setOf/mapOf are read-only; mutable* variants allow changes
  • map[key] returns null for missing keys
  • Default sets and maps keep insertion order
  • Expose read-only types from your APIs

Watch out for

  • Casting a read-only List to MutableList to modify it, which can fail or change shared data.

Check yourself

  1. What does mapOf("a" to 1)["b"] return?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: kotlinlang.org/docs/collections-overview.html