find和firstOrNull有什么区别?

时间:2017-08-05 09:18:30

标签: collections kotlin

鉴于从Kotlin Koans中提取以下代码:

fun Shop.findAnyCustomerFrom(city: City): Customer? {
    // Return a customer who lives in the given city, or null if there is none
    return customers.firstOrNull { it.isFrom(city) }
}

我自己的解决方案使用customers.find。两者都适用于公案场景。

firstOrNullfind的文档似乎非常相似。

这两个功能有什么区别?

1 个答案:

答案 0 :(得分:17)

在2014年的这篇帖子中,Kotlin社区成员和JetBrains工作人员讨论了不同方法findfirstOrNull的优点:

https://youtrack.jetbrains.com/issue/KT-5185

虽然不是官方声明,JetBrains的员工Ilya Ryzhenkov将其描述为:

  

我认为我们可以取消更新find并将其设为firstOrNull的别名。就像indexOf具有众所周知的语义一样,find也被广泛认为是“找到第一个匹配谓词的项目,如果没有找到则返回null”。喜欢精确含义的人可以使用firstOrNullsingleOrNull来表达意图。

换句话说:

  • find(predicate)firstOrNull(predicate)的行为相同,find可以被视为firstOrNull的别名
  • find作为别名保留,因为对于那些不熟悉这些Linq风格或功能性方法的程序员来说,它更直观,易于发现。

实际上Array<out T>.find的定义没有被定义为别名,而是作为包装器定义(尽管优化编译器将内联它,有效地使其成为别名):
https://github.com/JetBrains/kotlin/blob/1.1.3/libraries/stdlib/src/generated/_Arrays.kt#L657

@kotlin.internal.InlineOnly
public inline fun <T> Array<out T>.find(predicate: (T) -> Boolean): T? {
    return firstOrNull(predicate)
}

Sequence<T>.find同上:
https://github.com/JetBrains/kotlin/blob/1.1.3/libraries/stdlib/src/generated/_Sequences.kt#L74

@kotlin.internal.InlineOnly
public inline fun <T> Sequence<T>.find(predicate: (T) -> Boolean): T? {
    return firstOrNull(predicate)
}

(我自己不是Kotlin用户,但我很惊讶这些方法是作为为每个集合类型手动定义的编译时生成的代码实现的,而不是作为单个JVM泛型方法实现 - 是否有一些原因?)