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

Lists

Lists are like arrays, but they are more flexible, because the sequence of values can grow or shrink after it has been created. They work in a similar way to Python lists.

List Creation

Creating a list follows the same pattern that we saw for arrays. It can be done by specifying element type, size, and some code that generates an initial value:

val numbers = List<Float>(100) { 0.0f }

val greetings = List<String>(5) { "Hello" }

Alternatively, you can provide the list contents as arguments to the listOf() function:

val numbers = listOf(9, 3, 6, 2)

val names = listOf("Nine", "Three", "Six", "Two")

[Run this code]

There are a few differences between lists and arrays, however.

One difference is that you can pass a list to the println() function and see the list contents displayed on the console. You can’t do that with arrays1.

Another difference is that there is no such thing as a more efficient ‘list of primitives’. So there is no IntList class and no intListOf() function, for example.

Element Access

You can use [], get() and slice() to access list elements, just as you can with array elements.

Try this out now.

  1. Edit the file List.kt, in the tasks/task7_3_1 subdirectory of your repository.

    In this file, write a program that uses these two lines to create and display a list of integers:

    val numbers = listOf(9, 3, 6, 2, 8, 5)
    println(numbers)
    

    Check that this compiles and runs successfully.

  2. Add a line of code that prints the value of numbers[0]. Add another line that prints the value of numbers.get(0). You should see 9 printed twice after you recompile and and run the program.

  3. Add a line that attempts to print the value of numbers[10]. What do you think will happen when you recompile and run the program?

    Try it to see if you are right.

  4. Comment out the line that caused the problem, using //. Then add a line that prints the value of numbers.slice(2..4).

  5. Add a line that prints the value of numbers.first(). Then add a line that prints the value of numbers.last(). What do you think would happen if these operations were performed on an empty list?

    (Try this out, if you like!2)

  6. Add a line that assigns a new value to numbers[0]. What do you see when you try to compile the program?

  7. Replace the offending line with one that attempts to add a new value to the list:

    numbers.add(1)
    

    What happens now when you try to compile the program?

Important

Kotlin prefers immutability.

Lists created using the List<> constructor or the listOf() function are immutable by design. This means that you cannot add a new value to such a list, remove any of its values, or replace any of its values.

However, note that the the objects in the list could still change state, if they are of a type that supports such operations.

Mutable Lists

If you want your list to change after creation, you need to be explicit about this. For example, you can specify MutableList<> instead of List<>:

val greetings = MutableList<String>(5) { "Hello" }

greetings.set(0, "Hi there")   // OK: greetings is mutable

Alternatively, you can use the mutableListOf() function:

val numbers = mutableListOf(9, 3, 6, 2)

numbers[0] = 1   // OK: numbers is mutable

mutableListOf() is also the most convenient way of creating an empty mutable list—although in this case you will need to supply an element type in angle brackets, because there are no contents for type inference to work on:

val data = mutableListOf<Double>()

Adding & Removing Values

Mutable lists have a number of methods that can be used to modify the list:

MethodDescription
add()Adds an item at the end, or a given position
addAll()Adds all items from the given collection
remove()Removes first occurrence of the given item
removeAll()Removes all occurrences of the specified items
removeAt()Removes the item at the given position
clear()Empties the list of all its contents

Note that the removeAll() method expects to be given another collection, specifying the items to be removed. You can also specify the items it should remove by providing a predicate function that returns True for those items.

See the API documentation for MutableList for further details.

Task 7.3.2

  1. Copy List.kt from the task7_3_1 subdirectory of your repository to the task7_3_2 subdirectory.

  2. Modify this copy of List.kt so that it uses the mutableListOf() function to create the list. Check that this fixes the compiler errors found in the previous task.

  3. Add some code to List.kt that demonstrates the list modification methods in the table above. After calling each method, add a line that prints the list, so that you can see the effect of the call.


  1. This has to do with the underlying implementations of collections. On the JVM, a Kotlin array is implemented as a Java array, which doesn’t support the automatic conversion of array contents to a string for printing. A Kotlin list, on the other hand, is implemented by a Java class that does support automatic conversion of contents to a string.

  2. You can use listOf<Int>() to create the empty list here.