Start learning free

LESSON 100 OF 348 · ARRAYS I

Removing Items From a List in Kotlin: removeAt()

Lesson Read the full explanation

Another way to change the data in an ArrayList is with the .removeAt() method.

.removeAt() takes one parameter which represents an index and removes the element placed at that index:

val threeArr = mutableListOf(1, 4, 6)

// Remove second element:
threeArr.removeAt(1)

// threeArr has now the value [1, 6]

// Remove first element:
threeArr.removeAt(0)

// threeArr has now the value [6]

Assignment
Follow the Coding Tutorial and let's play with some arrays.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 2
    Ctrl + Enter to check

    KOTLIN · ARRAYS I

    Array Pop in Kotlin, explained

    Removing by position

    Kotlin has no pop function. To take an item out of a MutableList by its position, call removeAt with an index. The item at that index disappears, and every item after it moves one step toward the front:

    val threeArr = mutableListOf(1, 4, 6)
    
    threeArr.removeAt(1)
    println(threeArr)  // [1, 6]
    
    threeArr.removeAt(0)
    println(threeArr)  // [6]
    

    The list is one item shorter after every call. Like add, removeAt exists only on a MutableList. A list made with listOf is read-only and has no such function.

    Removing the last item

    The last item of a list sits at index size - 1. Passing that index to removeAt removes the last item, which is what pop does in other languages:

    val fruits = mutableListOf("mango", "kiwi", "grapefruit")
    
    fruits.removeAt(fruits.size - 1)
    println(fruits)  // [mango, kiwi]
    

    size is a property, so it is written without parentheses. The expression fruits.size - 1 is evaluated before the call, while the list still has three items, so the index is 2.

    removeAt also returns the item it removed, so you can keep it:

    val removed = fruits.removeAt(0)
    println(removed)  // mango
    println(fruits)   // [kiwi]
    

    removeAt versus remove

    A list also has remove(item), which looks for a value and removes its first occurrence. The two functions do different jobs:

    • removeAt(index) removes by position.
    • remove(item) removes by value, and returns true if the value was found.

    With a list of integers, the difference is easy to forget:

    val nums = mutableListOf(10, 20, 30)
    
    nums.remove(10)    // removes the value 10
    println(nums)      // [20, 30]
    
    nums.removeAt(1)   // removes the item at index 1
    println(nums)      // [20]
    

    Here remove(10) removes the value 10, not the item at index 10. For a list like [5, 6, 7], calling remove(7) removes the value 7, but removeAt(7) would throw an IndexOutOfBoundsException, because the list has no index 7.

    The exercise

    The starting code has two lists:

    val fruits = mutableListOf("mango", "kiwi", "grapefruit")
    val ages = mutableListOf(14, 32, 50, 21)
    
    1. Remove the last item of fruits. Call removeAt with fruits.size - 1, the index of "grapefruit".
    2. Remove the last two items of ages. Call removeAt(ages.size - 1) twice. The first call removes 21. After it, the list has three items, so the same expression now evaluates to the new last index and the second call removes 50.
    val fruits = mutableListOf("mango", "kiwi", "grapefruit")
    val ages = mutableListOf(14, 32, 50, 21)
    
    fruits.removeAt(fruits.size - 1)
    ages.removeAt(ages.size - 1)
    ages.removeAt(ages.size - 1)
    

    Afterwards, fruits is [mango, kiwi] and ages is [14, 32]. Because the index is calculated from size each time, the second call needs no change even though the list got shorter.

    Removing more than one item

    Calling removeAt repeatedly is fine for a couple of items, and Kotlin has bulk operations for the rest:

    • removeAll { it % 2 == 0 } removes every item for which the condition is true. On [1, 2, 3, 4, 5, 6] it leaves [1, 3, 5].
    • clear() removes everything and leaves an empty list.

    Be careful with indices when you remove inside a loop. Each removal shifts the later items, so an index you computed before the removal may now point at a different item, or past the end. Removing from the end, as this lesson does, avoids the problem because nothing after the removed item has to move.

    Reading the list after each step

    It helps to trace the exercise on paper. The list ages starts as [14, 32, 50, 21] with a size of 4. The first call removes the item at index 3, leaving [14, 32, 50] with a size of 3. The second call removes the item at index 2, leaving [14, 32]. Each call asks for the size of the list as it is at that moment, which is why one expression works for both calls.

    Shortcuts and empty lists

    Kotlin also has removeLast(), which removes and returns the last item without any arithmetic. Both it and removeAt(list.size - 1) fail on an empty list: the index would be -1, and removeAt(-1) throws IndexOutOfBoundsException. When the list may be empty, removeLastOrNull() returns null instead of failing:

    val empty = mutableListOf<Int>()
    
    println(empty.removeLastOrNull())  // null
    

    Common mistakes

    • Using removeAt(fruits.size). The size is one past the last index, so this throws.
    • Using remove when you mean removeAt. On a list of integers, the argument is treated as a value, not a position.
    • Hard-coding the index. removeAt(3) works on a four-item list and breaks on a three-item one. size - 1 follows the list.
    • Removing from an empty list. There is no item to remove, so the call throws.

    Key takeaways

    • removeAt(index) removes the item at a position and returns it.
    • The last index is size - 1, so removeAt(list.size - 1) removes the last item.
    • remove(item) works on values, not positions.
    • Only a MutableList can change its size.
    Keep going with KotlinAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free