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

时间:2018-01-28 21:08:59

标签: java java-8 functional-programming kotlin java-stream

我试图在列表中找到符合条件(过滤)的前两个元素,为此我在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循环,但我想使用函数式编程方法。

2 个答案:

答案 0 :(得分:11)

默认情况下,Kotlin执行这些操作急切,而Java中的 Streams lazy 。如果您使用sequences,则可以在Kotlin中使用相同的行为,这可以使用ArrayIterablearr.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转换为序列,执行filtertake(类似于Java limit),然后将其转回列表,它会懒洋洋地表演。

来自the documentation for Sequence

  

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