我试图在列表中找到符合条件(过滤)的前两个元素,为此我在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循环,但我想使用函数式编程方法。
答案 0 :(得分:11)
默认情况下,Kotlin执行这些操作急切,而Java中的 Streams 是 lazy 。如果您使用sequences,则可以在Kotlin中使用相同的行为,这可以使用Array
从Iterable
或arr.asSequence().filter { i ->
println("Filter: $i")
i % 2 == 0
}.take(2).toList()
//Filter: 0
//Filter: 1
//Filter: 2
轻松生成。
//--- ./validation.js
// importing common functions
import * as common from './common.js';
export function validateInput($el)
{
let type = $el.data('validation-type').split('|');
let val = $el.val();
// some whitelisting logic
// and traversing the type-array
var functionName = valid[type[i]]; // valid.email() below
// how the call looks now
var result = functionName(val);
}
var valid = {
email: function(val) {
// some validation logic
return true;
}
}
请注意,序列必须最终转换回列表。
您可以阅读详细信息asSequence()
。
答案 1 :(得分: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]
将arr
转换为序列,执行filter
和take
(类似于Java limit
),然后将其转回列表,它会懒洋洋地表演。
来自the documentation for Sequence:
通过迭代器返回值的序列。这些值是懒惰地评估的,序列可能是无限的。