Kotlin Tip #29: Use Sequences to Boost Performance in Large Data Processing — 100 Kotlin Tips in 100 Days

Raphael De Lio
Kotlin with Raphael De Lio
3 min readMar 9, 2024

Twitter | LinkedIn | YouTube | Instagram
Tip #28: Use require() for argument validation in functions or constructors

Imagine you have a list with of numbers and you want to get the square root of all the odd numbers and then find the first number that is greater than 100. One way of doing that is by filtering all the odd numbers, then iterate over the result, square all of them and then iterate over the list again to find the first number that is greater than one thousand:

val numbers = (1..20) // Create a list from 1 to 20
val oddSquared = numbers
.filter { it % 2 != 0 } // Filter for odd numbers
.map { it * it } // Square the filtered numbers
.first { it > 10 } // Find the first that is greater than 10

The problem here is that every step works on the whole list or the result from the step before it. This creates extra lists that use up memory. Also, it ends up working on parts of the list that aren’t needed for the final answer, which wastes effort. So, instead of being efficient, it does more work than necessary and uses more memory by making new lists at each step.

A more efficient way is by converting our list to a Sequence. With a Sequence, operations are not immediately executed. Instead, elements are processed one at a time in a chain of operations, and the processing stops as soon as the final condition is met:

val numbers = (1..20) // Create a list from 1 to 20
val oddSquared = numbers.asSequence() // Convert to a sequence
.filter { it % 2 != 0 } // Filter for odd numbers
.map { it * it } // Square the filtered numbers
.first { it > 10 } // Find the first that is greater than 10

By using a sequence, no computation will happen when defining the filter operation for odd numbers or when defining the mapping operation to square numbers. The evaluation will only start processing when the result is actually required, and that happens when we call first().

The sequence processes the elements one by one: it takes the first element (1), checks if it's odd (it is), squares it (1), and checks if the result is greater than 10 (it's not). This process continues to the next element and repeats. When it reaches 5, the check for oddness passes, it's squared to 25, and since 25 is greater than 10, the iteration stops.

Now, let’s set up an experiment. We’ll work with a list of numbers and apply both filtering and mapping operations. To observe the behavior, we’ll add print statements within the operations.

First, we’ll show the eager evaluation using a list.

This code will print messages as it filters and maps each number, showing that all operations are performed immediately and on all elements.

Now, let’s demonstrate lazy evaluation using a sequence.

In this sequence example, the print statements within the filter and map operations will help illustrate when and how each element is processed.

By using lazy evaluation with sequences, Kotlin allows for more efficient data processing, especially in scenarios where you might not need to process an entire collection to obtain your desired result.

However, keep in mind that while asSequence can improve performance, it's not a silver bullet for all collection processing scenarios. For small collections or simple operations, the overhead of converting to and from a sequence might outweigh its benefits.

I hope you have enjoyed this tip of our series! Don’t forget to subscribe and stay tuned for more Kotlin tips!

Stay curious!

Tip #30: Use reified type parameters to avoid type erasure

Contribute

Writing takes time and effort. I love writing and sharing knowledge, but I also have bills to pay. If you like my work, please, consider donating through Buy Me a Coffee: https://www.buymeacoffee.com/RaphaelDeLio

Or by sending me BitCoin: 1HjG7pmghg3Z8RATH4aiUWr156BGafJ6Zw

Follow Me on Social Media

Stay connected and dive deeper into the world of Kotlin with me! Follow my journey across all major social platforms for exclusive content, tips, and discussions.

Twitter | LinkedIn | YouTube | Instagram

--

--