Start learning free

LESSON 100 OF 414 · ARRAYS I

Array Length in Scala: size and the Last Index

Lesson Read the full explanation

We can get the number of elements in a Scala collection such as a List or an ArrayBuffer using .size.

val ages = List(14, 32, 50, 21)
println(ages.size)

// prints 4

Assignment
Follow the Coding Tutorial and print the list size.


Hint
Use ages.size.


STEP 1 OF 3
    Ctrl + Enter to check

    SCALA · ARRAYS I

    Array Length in Scala, explained

    Counting elements with size

    Every Scala sequence, whether a List, an Array or an ArrayBuffer, reports how many elements it holds with size:

    val ages = List(14, 32, 50, 21)
    println(ages.size) // 4
    

    The method length returns the same number, so ages.length works equally well. The count is the number of elements, not the last index. Because positions start at 0, a collection of size 4 has indexes 0, 1, 2 and 3.

    For an ArrayBuffer the size can change over time. After buffer += 99 the size is one larger, and after buffer.remove(0) it is one smaller. Each time you read size, you get the current count.

    Here is the size changing as a buffer grows and shrinks:

    val buffer = scala.collection.mutable.ArrayBuffer(14, 32, 50, 21)
    println(buffer.size) // 4
    buffer += 99
    println(buffer.size) // 5
    buffer.remove(0)
    println(buffer.size) // 4
    

    A List or an Array always keeps the size it was created with.

    Using the size to reach the end

    The last valid index is always size - 1, so you can read from the end without knowing the size in advance:

    println(ages(ages.size - 1)) // last element
    println(ages(ages.size - 2)) // second to last
    

    Scala indexes with parentheses, so ages(i) is correct and ages[i] is not. Square brackets are for type parameters such as List[Int]. For the ages above, ages.size - 1 is 3, which is the last position, and ages.size - 2 is 2.

    The exercise

    The lesson starts with two ArrayBuffer variables:

    val fruits = scala.collection.mutable.ArrayBuffer("mango", "kiwi", "grapefruit")
    val ages = scala.collection.mutable.ArrayBuffer(14, 32, 50, 21)
    

    Step 1: the size of fruits

    println(fruits.size) prints 3.

    Step 2: the last number of ages

    The size is 4, so the last index is 3. println(ages(ages.size - 1)) prints 21.

    Step 3: the second to last number

    Subtract 2 to step one position further back: println(ages(ages.size - 2)) prints 50.

    The finished program

    val fruits = scala.collection.mutable.ArrayBuffer("mango", "kiwi", "grapefruit")
    val ages = scala.collection.mutable.ArrayBuffer(14, 32, 50, 21)
    println(fruits.size)
    println(ages(ages.size - 1))
    println(ages(ages.size - 2))
    

    Its output:

    3
    21
    50
    

    Gotchas

    • Size is not an index. ages(ages.size) is one past the end and throws an IndexOutOfBoundsException. For the four ages, the message is 4 is out of bounds (min 0, max 3).
    • Empty collections. When the size is 0, size - 1 is -1, which is not a valid index. Check ages.nonEmpty or ages.size > 0 before reading the last element.
    • Shortcuts. ages.last returns the last element without any arithmetic. On an empty collection it throws a NoSuchElementException, just as an invalid index would fail.
    • Loops. A loop over all indexes uses 0 until ages.size. The range stops before the size, which keeps every index valid.

    Why the last index matters

    Code that depends on a typed-in number breaks when the data changes. Writing ages(3) works for four ages, but if a fifth is added at the end, it silently reads the fourth. The form ages(ages.size - 1) follows the collection, so it always reaches the real last element. For the same reason, loops use size as their bound instead of a literal.

    size versus length

    Both names exist because Scala sequences come from two traditions. length is the older name, used by Array and strings. size is the general name that works on every collection, including sets and maps, which have no positions at all. In this lesson's code either name is correct, so pick one and use it consistently. The collection type decides nothing here: fruits.size and fruits.length are both 3.

    Key takeaways

    • size and length give the number of elements.
    • The last index is size - 1, the second to last is size - 2.
    • For an ArrayBuffer, the size changes when you add or remove elements.
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free