Kotlin 集合:indexOfFirst 与查找

Kotlin Collection: indexOfFirst vs find

这可能是一个愚蠢的问题,但我不确定是否使用 indexOfFirst() 或 find() 作为“Returns 匹配给定 [predicate] 的第一个元素”。唯一的区别是一个 returns -1 和另一个 null。我什么时候应该使用 indexOfFirst() 或 find()。有没有一个比另一个的优势。考虑以下代码片段。

private val mPersonList = mutableListOf<Person>()

private fun findPerson(person: Person) {
    val position = mPersonList.indexOfFirst { it.name == person.name }
    if (position != -1) {
        doSomethingWithPerson(mPersonList[position])
    }
}

private fun findPersonWithFind(person: Person) {
    val foundPerson = mPersonList.find { it.name == person.name }
    foundPerson?.let { doSomethingWithPerson(it) }
}

private fun doSomethingWithPerson(foundPerson: Person) {
    //Do something
}

这两个函数做几乎相同的事情:它们都定位列表或数组中的第一个匹配项(即给定谓词 return 为真的第一个项)。

它们之间的区别很微妙:

最明显的是,indexOfFirst() 给出匹配项目的 index,而 find() 给出项目本身.

很明显,如果你有索引,你可以很容易地找到匹配的项目。 (而且,如果列表是随机访问的,例如 ArrayList,那么效率非常高——如果不是,则效率要低得多,例如 LinkedList。) 而如果您只有该项目,则无法找到它的索引无需再次调用 findindexOfindexOfFirst

所以如果你需要知道索引,那么只有indexOfFirst()就可以了;但如果你不这样做,那么 find() 可能会稍微简单一些。

问题中的代码属于后一类:findPerson() 获取位置但仅将其用于索引到列表中。所以这有点冗长,而且(如果列表不是随机访问的)可能比 findPersonWithFind().

慢很多

其次,如你所说,如果没有找到匹配项,indexOfFirst() returns -1,而find() returns null .

Kotlin 提供了许多安全使用 null 的方法(例如安全调用 ?. 运算符、elvis ?: 运算符、智能转换、可空接收器上的扩展函数以及许多有用的函数在标准库中)。但是没有处理 -1 的等价物,所以使用 find() 可能更容易安全地处理未找到的情况。

顺便说一句,find() 的替代名称 firstOrNull() 明确了可空性,尽管它也有不带谓词的重载,只是 return列表中的第一项(如果它不为空)。 (标准库正朝着 …OrNull() 函数名称的方向发展,可能是因为它使可空性非常明确,尤其是当它是一个通用的命名约定时。)

所以,你使用哪个取决于你的需要。

还值得了解一些相关功能。它们都有找到 last 匹配项的等效项:findLast()/lastOrNull(), and indexOfLast().

还有较旧的 indexOf() function, which checks for (equality with) a given object, instead of using a predicate.  (That, too, returns -1 if not found, which is probably why indexOfFirst() and indexOfLast() do the same.)  Though if the list is sorted, a binarySearch() or binarySearchBy 可能比完整扫描快很多。