sequenceOf() / generateSequence()
Kotlin's Sequence is a lazily evaluated collection. You can create one with sequenceOf() or generateSequence(), and convert an existing collection using asSequence(). Intermediate operations are not executed until a terminal operation is called.
Syntax
// sequenceOf — sequence of fixed elements
val seq = sequenceOf(1, 2, 3, 4, 5)
// generateSequence — infinite sequence (always limit with a terminal operation)
val naturals = generateSequence(1) { it + 1 } // 1, 2, 3, ...
val first10 = naturals.take(10).toList()
// asSequence — converts a list to a sequence
val list = listOf(1..100)
val result = list.asSequence()
.filter { it % 2 == 0 }
.map { it * it }
.take(5)
.toList() // executed when terminal operation is called
// sequence builder
val fib = sequence {
var a = 0; var b = 1
while (true) { yield(a); val t = a + b; a = b; b = t }
}
Method List
| Method / Function | Description |
|---|---|
| sequenceOf(elements...) | Creates a sequence from fixed elements. |
| generateSequence(seed) { next value } | Creates an (infinite) sequence where each next value is produced by a function. Returns null to end the sequence. |
| generateSequence { value or null } | Calls generateSequence without a seed value. |
| sequence { yield(value) } | Defines a complex sequence using a coroutine builder. |
| collection.asSequence() | Converts an existing collection to a sequence. |
| sequence.take(n) | Takes only the first n elements (intermediate operation). |
| sequence.filter { } | Filters elements with lazy evaluation (intermediate operation). |
| sequence.map { } | Transforms elements with lazy evaluation (intermediate operation). |
| sequence.toList() | Terminal operation — evaluates the sequence and converts it to a list. |
Sample Code
fun main() {
// sequenceOf — fixed elements
val seq = sequenceOf("A", "B", "C")
seq.forEach { print("$it ") }
println()
// generateSequence — infinite sequence of natural numbers
val naturals = generateSequence(1) { it + 1 }
println("First 10: ${naturals.take(10).toList()}")
// generateSequence — ends when null is returned
val countdown = generateSequence(10) { if (it > 1) it - 1 else null }
println("Countdown: ${countdown.toList()}")
println()
// sequence builder — Fibonacci sequence
val fibonacci = sequence {
var a = 0
var b = 1
while (true) {
yield(a)
val next = a + b
a = b
b = next
}
}
println("Fibonacci (15 items): ${fibonacci.take(15).toList()}")
println()
// asSequence — efficient processing with lazy evaluation
println("=== List vs Sequence ===")
// List (creates an intermediate list at each step)
val listResult = (1..1000000)
.filter { it % 2 == 0 } // creates a list of 500,000 items
.map { it * it } // creates another list of 500,000 items
.first()
println("First even number squared: $listResult")
// Sequence (stops as soon as the first match is found)
val seqResult = (1..1000000).asSequence()
.filter { it % 2 == 0 } // lazy (not yet executed)
.map { it * it } // lazy (not yet executed)
.first() // executed here — completes after processing 2 elements
println("Sequence result: $seqResult")
}
Notes
The biggest advantage of sequences is lazy evaluation. With lists, each intermediate operation creates a new collection. With sequences, nothing is executed until a terminal operation is called. Sequences are more efficient when you only need a small number of elements or when processing large datasets.
Note: When using infinite sequences, always limit the number of elements with take(), first(), or similar. Calling a terminal operation without a limit will cause an infinite loop.
For terminal operations on sequences, see Sequence — Terminal Operations. For use with coroutines, see Flow — Basics.
If you find any errors or copyright issues, please contact us.