Why use a list
A static array has a size fixed at creation. When the number of items changes while the program runs, you want a collection that can grow and shrink. In Kotlin that is a MutableList, and the usual implementation behind it is ArrayList, a resizable array. You create one by calling mutableListOf.
Creating a list
An empty list needs to know the type of its elements, because nothing else tells the compiler:
val names = mutableListOf<String>()
println(names.size)
names.add("kiwi")
names.add("mango")
println(names)
0
[kiwi, mango]
Unlike an array, a list prints its elements directly. add appends to the end, so the size grows from 0 to 2 here.
Declaring the type
You can also write the variable's type yourself, using the interface MutableList:
val sandwich: MutableList<String> = mutableListOf()
Here the type on the left tells Kotlin what mutableListOf() should hold, so the call needs no <String>. Declaring the interface type, rather than ArrayList, says what you need (a list you can change) without tying the code to one implementation.
Creating a list with values
When you know the values, pass them to mutableListOf:
val sandwich = mutableListOf("peanut butter", "jelly", "bread")
Kotlin infers the element type, String, from the arguments, so no annotation is needed.
Mutable and read-only lists
Kotlin separates lists you can change from lists you can only read. listOf(1, 2) gives a read-only List: it has no add, and assigning to an index doesn't compile. mutableListOf gives a MutableList, which has add, removeAt and index assignment. Choose mutableListOf when the contents will change.
Also note that val and mutability are separate things. val stops you from pointing the variable at another list. It doesn't stop you from adding to the list it already points to.
The exercise
- Create
fruits. CallmutableListOfwith the three strings. The element type is inferred asString. - Create
ages. CallmutableListOfwith the four numbers. The type is inferred asInt, and because the list is mutable, it can grow or shrink later.
val fruits = mutableListOf("mango", "kiwi", "grapefruit")
val ages = mutableListOf(14, 32, 50, 21)
The exercise prints nothing. Adding println(fruits) shows [mango, kiwi, grapefruit] and println(ages) shows [14, 32, 50, 21].
Common mistakes
- Using
listOfwhen you need to change the list. Callingaddon a read-only list gives an "unresolved reference" error. - Forgetting the type for an empty list.
val items = mutableListOf()doesn't compile, because there are no values to infer the type from. WritemutableListOf<String>()or give the variable a type. - Mixing types.
mutableListOf(1, "a")compiles, but the compiler can no longer treat the elements asIntor asString, which is rarely what you want. - Thinking
valmakes the list constant. It doesn't; uselistOfif you want a list that can't change.
Changing a list
The point of a mutable list is that it can change size. Three operations you will use often are add, which appends an item to the end; removeAt, which deletes the item at an index; and remove, which deletes the first item equal to a given value. The contains function tells you whether a value is present.
val sandwich = mutableListOf("peanut butter", "jelly")
sandwich.add("bread")
sandwich.removeAt(0)
println(sandwich)
sandwich.remove("jelly")
println(sandwich)
println(sandwich.contains("bread"))
[jelly, bread]
[bread]
true
Each call changes the same list in place. That is why sandwich can be a val: the variable keeps pointing at one list while the list's contents change.
Lists compared with arrays
An array made with arrayOf or IntArray has a fixed size and prints as an unreadable type name unless you call contentToString(). A list can grow, shrinks when you remove items, and prints its elements directly. For numbers, an IntArray stores plain values, while a MutableList<Int> stores boxed objects, so an array is a bit leaner when the size is known up front. When it isn't, a list is the better fit.
Key takeaways
mutableListOfcreates a resizable list backed by anArrayList.- Give the type in angle brackets or on the variable when the list starts empty.
listOfis read-only;mutableListOfallowsaddandremoveAt.valfixes the variable, not the contents.