我需要映射一个列表并检索第一个非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元素停止的用例是必不可少的。
答案 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()
:分别是函数 firstNotNullOf
和 firstNotNullOfOrNull
。
它们对每个元素执行一次 transform
函数,并在遇到该函数的第一个非空结果时立即停止,因此它们是短路的。