Lesson 11 / 25
Collections and Sequences
map, filter, groupBy, fold and lazy sequences.
Read-only by default
Kotlin distinguishes read-only interfaces (List, Set, Map) from mutable ones (MutableList and so on), created with listOf or mutableListOf. The standard library offers many operations: map, filter, flatMap, associateBy, groupBy, partition, sortedBy, sumOf, fold, reduce, any, all, firstOrNull, chunked, windowed and more. Each collection operation is eager and creates an intermediate list. A sequence (asSequence() or sequence { }) is lazy: elements pass through the whole chain one at a time, and processing stops early with operations like first or take. Sequences help with long chains on large data; for small collections plain lists are usually fine.
Summarising orders
Eager list operations and a lazy sequence.
data class Order(val customer: String, val total: Double, val paid: Boolean)
fun main() {
val orders = listOf(
Order("ada", 30.0, true), Order("linus", 12.5, false), Order("ada", 7.5, true)
)
val revenueByCustomer: Map<String, Double> = orders
.filter { it.paid }
.groupBy { it.customer }
.mapValues { (_, list) -> list.sumOf { it.total } }
val (paid, unpaid) = orders.partition { it.paid }
val count = orders.fold(0) { acc, order -> if (order.total > 10) acc + 1 else acc }
val firstBigSquare = generateSequence(1) { it + 1 } // infinite, lazy
.map { it * it }
.first { it > 1_000 }
}Use OrNull variants
Functions like first() and single() throw on no match; firstOrNull(), singleOrNull() and getOrNull(i) return null and combine nicely with ?:.
Quick check: What is the key difference between a List chain and a Sequence chain?
- Sequences are mutable lists
- Sequences are always faster
- Lists cannot be filtered
- Sequences are evaluated lazily, element by element
Answer
Sequences are evaluated lazily, element by element — Lazy evaluation avoids intermediate collections and allows early termination.