Kotlin短路图{} .firstOrNull {}

时间:2017-01-13 10:00:00

标签: kotlin

我需要映射一个列表并检索第一个非null元素,我需要将map操作短路,就像它应该在Java 8流API中一样。在没有Java 8流的情况下,有没有一种方法可以在Kotlin中执行此操作?

我创建了自己的扩展方法来执行此操作:

fun <T, R> Iterable<T>.firstNonNullMapping(transform: (T) -> R?): R? {
    for (element in this) {
        val result = transform(element)
        if (result != null) {
            return result
        }
    }
    return null
}

测试证明这是有效的

val firstNonNullMapping = listOf(null, 'a', 'b')
        .firstNonNullMapping {
            assertNotEquals(it, 'b') // Mapping should be stopped before reaching 'b'
            it
        }
assertEquals(firstNonNullMapping, 'a')
然而, IntelliJ建议我用更整洁的

替换我的for循环
return this
        .map { transform(it) }
        .firstOrNull { it != null }

问题是这将映射iterable的所有元素,并且对于我的第一个非null元素停止的用例是必不可少的。

3 个答案:

答案 0 :(得分:11)

Kotlin懒惰地评估了与Java 8流相对应的sequences,而不是在集合上调用stream(),您调用asSequence()

return this
        .asSequence()
        .map { transform(it) }
        .firstOrNull { it != null }

答案 1 :(得分:0)

我想知道什么是更快的,@ ingoKegel的解决方案,或者这个:

return this.firstOrNull { transform(it) != null }?.let { transform(it) }

答案 2 :(得分:0)

Kotlin 1.5 提供了组合的快捷方式替代 .asSequence().mapNotNull { ... }.first/firstOrNull():分别是函数 firstNotNullOffirstNotNullOfOrNull

它们对每个元素执行一次 transform 函数,并在遇到该函数的第一个非空结果时立即停止,因此它们是短路的。