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。) 而如果您只有该项目,则无法找到它的索引无需再次调用 find
、indexOf
或 indexOfFirst
!
所以如果你需要知道索引,那么只有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
可能比完整扫描快很多。
这可能是一个愚蠢的问题,但我不确定是否使用 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。) 而如果您只有该项目,则无法找到它的索引无需再次调用 find
、indexOf
或 indexOfFirst
!
所以如果你需要知道索引,那么只有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
可能比完整扫描快很多。