Reputation: 3603
forEach
which means, that only 20 integers will be looked at? 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
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
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