1. Overview
In this article, we will see an example of the Kotlin sequence.
The Kotlin Standard Library offers two ways of working with collections based on how they’re evaluated:
- eagerly:
Collection
- lazily:
Sequence
The difference between Collection and Sequence lies in when each transformation on the collection is performed.
2. Kotlin sequence
The sequences (Sequence<T>
) offer multi-step collection processing.
The Sequence performs all the processing steps one by one for every single element. In turn, Iterable
completes each step for the whole collection and then proceeds to the next step.
3. Sequence processing example
Let’s look at the Sequence
with an example.
3.1. Iterable
When the processing of an Iterable
includes multiple steps, they are executed eagerly: each processing step completes and returns its result – an intermediate collection. The following step executes on this collection.
Assume that you have a list of words. The code below filters the words longer than three characters and prints the lengths of the first four such words.
val words = "The quick brown fox jumps over the lazy dog".split(" ") val lengthsList = words.filter { println("filter: $it"); it.length > 3 } .map { println("length: ${it.length}"); it.length } .take(4) println("Lengths of first 4 words longer than 3 chars:") println(lengthsList)
When you run this code, you’ll see that the filter()
and map()
functions are executed in the same order as they appear in the code. First, you see filter:
for all elements, then length:
for the elements left after filtering, and then the output of the two last lines.
This is how the list processing goes:
3.2. Sequence
Multi-step processing of sequences is executed lazily when possible: actual computing happens only when the result of the whole processing chain is requested.
Now let’s write the same with sequences:
val words = "The quick brown fox jumps over the lazy dog".split(" ") val wordsSequence = words.asSequence() val lengthsSequence = wordsSequence.filter { println("filter: $it"); it.length > 3 } .map { println("length: ${it.length}"); it.length } .take(4) println("Lengths of first 4 words longer than 3 chars") println(lengthsSequence.toList())
The output of this code shows that the filter()
and map()
functions are called only when building the result list. So, you first see the line of text “Lengths of..”
and then the sequence processing starts.
Note that for elements left after filtering, the map executes before filtering the next element. When the result size reaches 4, the processing stops because it’s the largest possible size that take(4)
can return.
The sequence processing goes like this:
In this example, the sequence processing takes 18 steps instead of 23 steps to do the same with lists.
4. Conclusion
To sum up, we have seen an example of the Kotlin sequence.