aschoerk
aschoerk

Reputation: 3603

Stream handling in kotlin

Code:

class Tests {
    @Test
    fun test() {
        var counter = 0
        (1..10_000_000).filter { it % 2 == 1 }.forEach {
            counter++
            if (counter > 10)
                return
        }
    }
}

Upvotes: 2

Views: 135

Answers (2)

hotkey
hotkey

Reputation: 148189

Your code sample uses operations on Iterable<T>, which works eagerly: the .filter { ... } call will process the whole range and produce a list storing intermediate results.

To alter that, consider using Sequence<T> (e.g. with .asSequence()) that works lazily, so that the intermediate operations such as .filter { ... } produce another lazy sequence and only do the work when items are queried by terminal operations such as .forEach { ... }:

(1..10000000).asSequence()
    .filter { it % 2 == 1 } 
    .forEach { /* ... */ }

See: Kotlin's Iterable and Sequence look exactly same. Why are two types required?

Upvotes: 5

s1m0nw1
s1m0nw1

Reputation: 82117

You can actually see the answer to your question pretty quickly by just adding println(it) into filter:

//...
.filter {
   println(it)
   it % 2 == 1
}
//...

You'll see every number printed. That's because your processing works eagerly as explained here.

As already suggested, lazy Sequences to the rescue: (1..10_000_000).asSequence()

Now, the println(it) in filter will only print the numbers 1..21, which is definetly preferable in your example.

Upvotes: 1

Related Questions