Kotlin Tutorial · Functional Kotlin and Collections · Lesson 21 of 31

Kotlin Sequences

Process large or infinite data lazily with sequences instead of building intermediate lists.

Create a free account to save this page, take notes and track your progress. Sign in

Eager lists vs lazy sequences

List operations are eager: each step builds a full intermediate list. A sequence (asSequence()) is lazy: elements flow through the whole chain one at a time, and processing stops as soon as the result is known. The example counts how many elements each version touches.

Eager vs lazy evaluation
fun main() {
    var checked = 0
    val firstEager = (1..1_000).map { checked++; it * it }.first { it > 50 }
    println("list: $firstEager after $checked squares")

    checked = 0
    val firstLazy = (1..1_000).asSequence().map { checked++; it * it }.first { it > 50 }
    println("sequence: $firstLazy after $checked squares")
}

Output

list: 64 after 1000 squares
sequence: 64 after 8 squares

Run this on your computer — see “Get Started” for setup.

Generating sequences

generateSequence and sequence { yield(...) } create (possibly infinite) sequences; take what you need.

Infinite sequences
fun main() {
    val powersOfTwo = generateSequence(1) { it * 2 }
    println(powersOfTwo.take(8).toList())

    val fibonacci = sequence {
        var a = 0
        var b = 1
        while (true) {
            yield(a)
            val next = a + b
            a = b
            b = next
        }
    }
    println(fibonacci.filter { it % 2 == 0 }.take(5).toList())
}

Output

[1, 2, 4, 8, 16, 32, 64, 128]
[0, 2, 8, 34, 144]

Run this on your computer — see “Get Started” for setup.

Test yourself

When is a sequence better than a list for a chain of operations?

  1. Always
  2. For large or infinite data, or when processing can stop early
  3. For tiny lists
  4. When you need random access by index
Show answer

Answer: For large or infinite data, or when processing can stop early

Was this page helpful?