Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Kotlin Dictionary
  3. Sequences — Terminal Operations

Sequences — Terminal Operations

Kotlin sequences are evaluated lazily — they are not processed until a terminal operation is called. Terminal operations such as toList(), first(), and take() convert a sequence into a concrete value or collection.

Syntax

val seq = generateSequence(1) { it + 1 }  // infinite sequence

// toList — converts to a list (always limit with take first)
val list = seq.take(5).toList()            // [1, 2, 3, 4, 5]

// first / last — first/last element
val first = seq.take(10).first()           // 1
val firstEven = seq.first { it % 2 == 0 } // 2

// takeWhile / dropWhile — control with a condition
val lessThan5 = seq.takeWhile { it < 5 }.toList()  // [1, 2, 3, 4]

Method List

Terminal OperationDescription
sequence.toList()Converts the entire sequence to a list. For infinite sequences, call take() first.
sequence.toSet()Converts the sequence to a set.
sequence.take(n)Returns a sequence of the first n elements. Also acts as an intermediate operation.
sequence.takeWhile { condition }Returns elements while the condition is true. Stops as soon as it becomes false.
sequence.drop(n)Skips the first n elements.
sequence.dropWhile { condition }Skips elements while the condition is true, then returns the rest.
sequence.first()Returns the first element.
sequence.first { condition }Returns the first element matching the condition.
sequence.firstOrNull { condition }Returns the first element matching the condition, or null if none is found.
sequence.count()Returns the number of elements. Only use with finite sequences.
sequence.sum() / average()Calculates the sum or average. Only use with finite sequences.
sequence.forEach { }Executes an action for each element.

Sample Code

fun main() {
    // infinite sequence of natural numbers
    val naturals = generateSequence(1) { it + 1 }

    // take — first N elements
    println("First 10: ${naturals.take(10).toList()}")

    // takeWhile — while the condition is true
    println("Less than 10: ${naturals.takeWhile { it < 10 }.toList()}")

    // combining drop and take (pagination)
    val page2 = naturals.drop(10).take(5).toList()  // 11–15
    println("Page 2: $page2")

    println()

    // first — first element satisfying a condition
    val firstSquare = naturals.first { it * it > 50 }
    println("First square greater than 50: $firstSquare × $firstSquare = ${firstSquare * firstSquare}")

    // firstOrNull — returns null if not found
    val seq = sequenceOf(1, 3, 5, 7, 9)
    println("Even number: ${seq.firstOrNull { it % 2 == 0 }}")  // null

    println()

    // prime number sequence (simplified Sieve of Eratosthenes)
    fun primes(): Sequence<Int> = sequence {
        val sieve = mutableSetOf<Int>()
        var n = 2
        while (true) {
            if (n !in sieve) {
                yield(n)
                sieve.addAll(generateSequence(n * n) { it + n }.takeWhile { it < 1000 })
            }
            n++
        }
    }

    println("First 10 primes: ${primes().take(10).toList()}")
    println("Primes up to 50: ${primes().takeWhile { it <= 50 }.toList()}")

    println()

    // use asSequence to process a list efficiently
    val data = (1..10000).toList()
    val result = data.asSequence()
        .filter { it % 3 == 0 }   // multiples of 3
        .map { it * it }           // square
        .take(5)                   // first 5 results
        .toList()
    println("Squares of multiples of 3 (5 results): $result")  // [9, 36, 81, 144, 225]
}

Notes

takeWhile() and dropWhile() are essential for controlling sequence boundaries by condition. Because they stop (takeWhile) or start (dropWhile) the moment the condition becomes false for the first time, they are well suited for extracting ranges from sorted data or controlling infinite sequences.

Intermediate sequence operations (such as filter, map, and take) return a new sequence object, while terminal operations (such as toList, first, and count) return a concrete value. No processing occurs until a terminal operation is called.

For creating sequences, see sequenceOf() / generateSequence(). For asynchronous streams using coroutines, see Flow — Basics.

If you find any errors or copyright issues, please .