这个问题在这里已有答案:
我试图在列表中找到符合条件(过滤)的前两个元素,为此我在kotlin中实现了以下代码:
val arr = 0 until 20
val res = arr.filter { i ->
println("Filter: $i")
i % 2 == 0
}.take(2)
一切都很好,直到我意识到它过滤整个列表,无论是否找到了这两个元素。
使用Java 8 stream api,它按预期工作。
val res2 = arr.toList().stream()
.filter { i ->
println("Filter: $i")
i % 2 == 0
}.limit(2)
所以我的问题是如果只使用Kotlin功能就可以实现。
我知道我可以使用一个简单的for循环,但我想使用函数式编程方法。
默认情况下,Kotlin急切地进行这些操作,而Java中的Streams则是懒惰的。如果使用sequences,可以在Kotlin中使用相同的行为,Array
可以很容易地从Iterable
s或asSequence()
s生成arr.asSequence().filter { i ->
println("Filter: $i")
i % 2 == 0
}.take(2).toList()
//Filter: 0
//Filter: 1
//Filter: 2
。
here
请注意,序列必须最终转换回列表。
你可以阅读有关详细信息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]
。
通过使用序列,您可以像Java 8流一样进行延迟评估。我用懒惰的序列和显式类型重写了你的例子(我没有更改它们,我只是为了清楚而声明它们):
arr
通过将filter
变成一个序列,执行你的take
和limit
(就像Java的the documentation for Sequence),然后把它变成List,它会懒散地执行。
来自qazxswpoi:
通过迭代器返回值的序列。这些值是懒惰地评估的,并且序列可能是无限的。