← Back to Kotlin Course | Chapter 8: Collections | Lesson 5 of 7

Sequences

A Sequence processes items one at a time through every step before moving to the next item, instead of finishing one whole step for the entire group first.

Creating a Sequence

Calling .asSequence() on a collection converts it into a Sequence, which processes elements lazily rather than eagerly building intermediate lists at each step.

Example: Creating a Sequence

markup
fun main() {
    val numbers = (1..5).asSequence()
    println(numbers.toList())
}

Lazy Evaluation with map and filter

Chaining .map { } and .filter { } on a sequence just builds up a pipeline of operations -- nothing actually runs until a terminal operation is called.

Example: Lazy Evaluation with map and filter

markup
fun main() {
    val result = listOf(1, 2, 3, 4, 5)
        .asSequence()
        .map { println("Mapping $it"); it * 2 }
        .filter { it > 4 }
        .toList()
    println("Result: $result")
}

Terminal Operations Trigger Execution

Functions like .toList(), .first(), .count(), or .sum() are terminal operations -- calling one is what actually runs the whole lazy pipeline and produces a concrete result.

Example: Terminal Operations Trigger Execution

markup
fun main() {
    val firstBigSquare = (1..100).asSequence()
        .map { it * it }
        .first { it > 50 }
    println("First square over 50: $firstBigSquare")
}

Sequences vs Regular Collections

Regular List operations like .map() eagerly build a full new list at each step, while a Sequence processes each element through the whole pipeline before moving to the next -- useful for long chains over large data.

Note: For small collections, plain list operations are usually simpler and fast enough; sequences shine with large data or many chained steps.

Example: Sequences vs Regular Collections

markup
fun main() {
    val eagerResult = (1..5).map { it * 2 }.filter { it > 4 }
    val lazyResult = (1..5).asSequence().map { it * 2 }.filter { it > 4 }.toList()
    println("Eager: $eagerResult")
    println("Lazy: $lazyResult")
}
Common Mistakes
  1. Using a regular List chain of .map().filter() on a huge dataset and being surprised by unnecessary intermediate lists; a Sequence avoids this by being lazy.
  2. Forgetting to call .toList() (or another terminal operation) at the end of a sequence chain, since intermediate operations are lazy and don't run until a terminal one is invoked.
  3. Assuming sequences are always faster; for small collections, the overhead of building a sequence can outweigh the benefit compared to plain list operations.
Chapter Summary
  • asSequence() converts a collection into a Sequence, which evaluates operations lazily, element by element.
  • Intermediate operations (map, filter) on a sequence build up a pipeline but don't run until a terminal operation is called.
  • Terminal operations like .toList(), .first(), or .sum() trigger the actual processing of a sequence.
  • Sequences avoid creating intermediate collections at each step, which can be more efficient for large data or long operation chains.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.