9.1.1.8.2 获取单个元素

原文链接: https://kotlinlang.org/docs/collection-elements.html

9.1.1.8.2 获取单个元素

Kotlin 集合提供了一组用于从集合中获取单个元素的函数。本页描述的函数对列表和集都适用。

正如列表的定义所说,列表是有序集合。因此,列表的每个元素都有可用于引用的位置。除本页描述的函数之外,列表还提供了更多按索引获取和搜索元素的方式。更多细节请参阅 List 特有操作。

而按定义,集不是有序集合。不过 Kotlin 的 Set 会以某种顺序存储元素。这可能是插入顺序(在 LinkedHashSet 中)、自然排序顺序(在 SortedSet 中)或其他顺序。一组元素的顺序也可能是不确定的。在这些情况下,元素仍然以某种方式有序,因此依赖元素位置的函数依然会返回结果。不过,除非调用者知道所用 Set 的具体实现,否则这些结果是不可预测的。

按位置获取

要获取特定位置上的元素,可以使用 elementAt() 函数。把整数作为实参传入,你就会得到给定位置上的集合元素。第一个元素的位置是 0,最后一个是 (size - 1)。

elementAt() 对于不提供索引访问、或在静态类型上无法确定提供索引访问的集合很有用。对于 List,更符合语言习惯的做法是使用索引访问运算符(get() 或 [])。

1
2
3
4
5
6
7
8

fun main() {
    val numbers = linkedSetOf("one", "two", "three", "four", "five")
    println(numbers.elementAt(3))

    val numbersSortedSet = sortedSetOf("one", "two", "three", "four")
    println(numbersSortedSet.elementAt(0)) // 元素按升序存储
}

还有用于获取集合第一个和最后一个元素的有用别名:first() 和 last()。

1
2
3
4
5
6

fun main() {
    val numbers = listOf("one", "two", "three", "four", "five")
    println(numbers.first())
    println(numbers.last())
}

要避免获取不存在位置上的元素时抛出异常,请使用 elementAt() 的安全变体:

  • elementAtOrNull() 在指定位置超出集合边界时返回 null。
  • elementAtOrElse() 还会额外接收一个 lambda 函数,把 Int 实参映射为集合元素类型的实例。当传入越界位置时,elementAtOrElse() 会返回该 lambda 对给定值的处理结果。
1
2
3
4
5
6

fun main() {
    val numbers = listOf("one", "two", "three", "four", "five")
    println(numbers.elementAtOrNull(5))
    println(numbers.elementAtOrElse(5) { index -> "The value for index $index is undefined"})
}

按条件获取

函数 first() 和 last() 也让你可以按给定谓词在集合中搜索元素。当你传入测试集合元素的谓词调用 first() 时,会得到让谓词返回 true 的第一个元素。而带谓词的 last() 则返回匹配该谓词的最后一个元素。

1
2
3
4
5
6

fun main() {
    val numbers = listOf("one", "two", "three", "four", "five", "six")
    println(numbers.first { it.length > 3 })
    println(numbers.last { it.startsWith("f") })
}

如果没有元素匹配谓词,这两个函数都会抛出异常。要避免异常,请改用 firstOrNull() 和 lastOrNull():在没有找到匹配元素时它们返回 null。

1
2
3
4
5

fun main() {
    val numbers = listOf("one", "two", "three", "four", "five", "six")
    println(numbers.firstOrNull { it.length > 6 })
}

如果它们的名字更贴合你的场景,也可以使用以下别名:

1
2
3
4
5
6

fun main() {
    val numbers = listOf(1, 2, 3, 4)
    println(numbers.find { it % 2 == 0 })
    println(numbers.findLast { it % 2 == 0 })
}

带选择器获取

如果你需要在获取元素之前先映射集合,可以使用 firstNotNullOf() 函数。它结合了两个动作:

  • 用选择器函数映射集合
  • 返回结果中第一个非空值

如果结果集合中不存在非空元素,firstNotNullOf() 会抛出 NoSuchElementException。这种情况下可以使用对应的 firstNotNullOfOrNull() 来返回 null。

1
2
3
4
5
6
fun main() {
    val list = listOf<Any>(0, "true", false)
    // 把每个元素转换为字符串并返回第一个长度满足要求的元素
    val longEnough = list.firstNotNullOf { item -> item.toString().takeIf { it.length >= 4 } }
    println(longEnough)
}

随机元素

如果你需要获取集合中的任意元素,请调用 random() 函数。你既可以在不带参数的情况下调用它,也可以传入一个 Random 对象作为随机源。

1
2
3
4
5

fun main() {
    val numbers = listOf(1, 2, 3, 4)
    println(numbers.random())
}

在空集合上,random() 会抛出异常。要改为得到 null,请使用 randomOrNull()

检查元素是否存在

要检查集合中是否存在某个元素,请使用 contains() 函数。如果存在与函数实参 equals() 相等的集合元素,它返回 true。你可以用 in 关键字以运算符形式调用 contains()。

要一次检查多个实例是否都存在,请把包含这些实例的集合作为实参调用 containsAll()。

1
2
3
4
5
6
7
8
9

fun main() {
    val numbers = listOf("one", "two", "three", "four", "five", "six")
    println(numbers.contains("four"))
    println("zero" in numbers)

    println(numbers.containsAll(listOf("four", "two")))
    println(numbers.containsAll(listOf("one", "zero")))
}

此外,你可以通过调用 isEmpty() 或 isNotEmpty() 检查集合是否包含任何元素。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

fun main() {
    val numbers = listOf("one", "two", "three", "four", "five", "six")
    println(numbers.isEmpty())
    println(numbers.isNotEmpty())

    val empty = emptyList<String>()
    println(empty.isEmpty())
    println(empty.isNotEmpty())
}