Step 1 of 5 · Reading · ~3 min
Learn
Collections
Sequences
Chain map and filter on a List and each step builds a whole new list before the next step
starts. A Sequence does the opposite: it pulls one element all the way through the chain, then
the next one. Same method names, completely different schedule.
Watch the difference
fun main() {
val nums = listOf(1, 2, 3)
println("-- list --")
nums.map { println("map " + it); it * 2 }
.filter { println("filter " + it); it > 2 }
.first()
println("-- sequence --")
nums.asSequence()
.map { println("map " + it); it * 2 }
.filter { println("filter " + it); it > 2 }
.first()
}
//> -- list --
//> map 1
//> map 2
//> map 3
//> filter 2
//> filter 4
//> filter 6
//> -- sequence --
//> map 1
//> filter 2
//> map 2
//> filter 4
The list version does all the mapping, then all the filtering, then throws away everything after
the first match: six lambda calls to answer a question that needed two elements. The sequence
version stops the instant first() is satisfied — four calls, and element 3 is never touched
at all.
Intermediate and terminal operations
| Kind | Examples | What it does |
|---|---|---|
| Intermediate | map, filter, take, sortedBy | adds a stage to the pipeline; runs nothing |
| Terminal | toList, sum, count, first, forEach | pulls elements through and produces a result |
That split is the whole model, and it has a sharp edge. A sequence with no terminal operation does nothing whatsoever:
fun main() {
listOf(1, 2, 3).asSequence().map { println("seen " + it); it }
println("done")
}
//> done
Not one seen line. The pipeline was built and then never run.
✓ Add a terminal operation and the work happens:
listOf(1, 2, 3).asSequence().map { println("seen " + it); it }.toList()
When is a sequence actually worth it?
| Situation | Reach for |
|---|---|
| A handful of elements, one or two steps | List |
| A long chain over a large collection | Sequence |
| You only need the first few results | Sequence |
A source with no end, from generateSequence | Sequence — a List could not exist |
For small data a Sequence is usually slower: every element carries the cost of walking the
whole pipeline, and a list has none of that per-element bookkeeping. Do not sprinkle
.asSequence() everywhere. Switch in with .asSequence() when the chain is long or the source
is big, and finish with a terminal call to come back to a real collection.
Your exercise
Sum of Squares of Evens reads a line of space-separated integers and prints the sum of the squares of the even ones.
filter, map and sum on the plain list are exactly right here — the input is one short
line, so there is nothing for a sequence to save.
The mistake the grader catches lives in a hidden test that feeds 1 3 5 7. After the filter,
nothing is left, and the expected answer is 0. sum() on an empty list returns 0, so it
survives; reduce { a, b -> a + b } throws UnsupportedOperationException on an empty list and
fails the test outright. Use sum(). Print one integer with no other text.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…