Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any equivalent Kotlin function to Java 8 Stream limit function [duplicate]

I am trying to find the first two elements in a list that meet a condition (filtering), for that purpose I have implemented the following piece of code in kotlin:

val arr = 0 until 20

val res = arr.filter { i ->
        println("Filter: $i")
        i % 2 == 0
    }.take(2)

Everything was fine until I realized it filters through the whole list, no matter if the two elements have been found.

Making use of Java 8 stream api, it works as expected.

val res2 = arr.toList().stream()
     .filter { i ->
          println("Filter: $i")
          i % 2 == 0
     }.limit(2)

So my questions is if it can be achieved using only Kotlin functions.

I know I could use a simple for loop but I want to use a functional programming aproach.

like image 344
Omar Ham Avatar asked Jan 28 '18 21:01

Omar Ham


2 Answers

Kotlin, by default, does these kind of operations eagerly whereas Streams in Java are lazy. You can have the same behaviour in Kotlin if you work with sequences, which can easily be generated from Arrays or Iterables with asSequence().

arr.asSequence().filter { i ->
    println("Filter: $i")
    i % 2 == 0
}.take(2).toList()

//Filter: 0
//Filter: 1
//Filter: 2

Note that the sequence has to be transformed back to a list in the end.

You can read about the details here.

like image 90
s1m0nw1 Avatar answered Sep 26 '22 20:09

s1m0nw1


By using a sequence, you can get lazy evaluation like a Java 8 stream. I've rewritten your example with a lazy sequence and explicit types (I haven't changed them, I just declared them for clarity):

val arr: IntRange = 0 until 20

val res: List<Int> = arr
    .asSequence()
    .filter { i ->
        println("Filter: $i")
        i % 2 == 0
    }
    .take(2)
    .toList()

// Prints
Filter: 0
Filter: 1
Filter: 2
And res == [0, 2]

By turning arr into a sequence, performing your filter and take (which is like Java's limit), and turning it back into a List, it will perform lazily.

From the documentation for Sequence:

A sequence that returns values through its iterator. The values are evaluated lazily, and the sequence is potentially infinite.

like image 26
Todd Avatar answered Sep 25 '22 20:09

Todd