Java 8流限制功能是否有任何等效的Kotlin功能

Oma*_*Ham 5 java functional-programming java-8 kotlin java-stream

我试图在列表中找到符合条件(过滤)的前两个元素,为此我在kotlin中实现了以下代码:

val arr = 0 until 20

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

一切都很好,直到我意识到它过滤整个列表,无论是否找到了这两个元素.

使用Java 8 stream api,它按预期工作.

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

所以我的问题是如果只使用Kotlin功能就可以实现.

我知道我可以使用一个简单的for循环,但我想使用函数式编程方法.

s1m*_*nw1 11

默认情况下,Kotlin 急切地进行这些操作,而Java中的Streams则是懒惰的.如果你使用序列,你可以在Kotlin中具有相同的行为,这可以很容易地从Arrays或Iterables 生成asSequence().

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

//Filter: 0
//Filter: 1
//Filter: 2
Run Code Online (Sandbox Code Playgroud)

请注意,序列必须最终转换回列表.

你可以在这里阅读详细信息.


Tod*_*odd 7

通过使用序列,您可以像Java 8流一样进行延迟评估.我用懒惰的序列和显式类型重写了你的例子(我没有更改它们,我只是为了清楚而声明它们):

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]
Run Code Online (Sandbox Code Playgroud)

通过转动arr成序列,执行你的filtertake(类似于Java的limit),并把它放回一个列表,它会懒洋洋地执行.

序列的文档:

通过迭代器返回值的序列.这些值是懒惰地评估的,并且序列可能是无限的.