Kotlin 语言参考文档 中文版 Help

过滤(Filtering)集合

在对集合的处理中, 过滤是最常见的任务之一. Kotlin 中, 过滤条件使用 判定条件(predicate) 来表示 – 它是一个 lambda 函数, 接受的参数是集合元素, 返回结果是布尔值: true 代表这个元素满足判定条件, false 表示不满足判定条件.

标准库提供了一组扩展函数, 你可以只通过一次函数调用就能过滤集合. 这些函数不修改原来的集合, 因此对 可变集合和只读集合 都可以使用. 要操作过滤后的结果集合, 你应该将它赋值给一个变量, 或者在过滤之后链式调用其他函数.

使用判定条件进行过滤

最基本的过滤函数是 filter(). 调用这个函数时使用判定条件作为参数, filter() 函数会返回集合中满足这个判定条件的元素. 对于 ListSet, 结果集合都是 List, 对于 Map, 结果集合也是 Map.

fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") val longerThan3 = numbers.filter { it.length > 3 } println(longerThan3) val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11) val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10} println(filteredMap) //sampleEnd }

filter() 函数的判定条件中, 只能检查元素的值. 如果在过滤时还想使用元素的位置, 请使用 filterIndexed() 函数. 这个函数的判定条件接受两个参数: 第一个是元素下标, 第二个是元素值.

如果要按照相反的条件来过滤集合, 请使用 filterNot() 函数. 它返回判定条件结果为 false 的元素.

fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") val filteredIdx = numbers.filterIndexed { index, s -> (index != 0) && (s.length < 5) } val filteredNot = numbers.filterNot { it.length <= 3 } println(filteredIdx) println(filteredNot) //sampleEnd }

还有一些函数, 可以根据元素的类型进行过滤, 得到元素类型缩窄后的集合:

  • filterIsInstance() 函数返回指定类型的集合元素. 对 List<Any> 调用这个函数时, filterIsInstance<T>() 返回的结果集合类型为 List<T>, 因此你可以对结果集合的元素调用类型 T 的函数.

    fun main() { //sampleStart val numbers = listOf(null, 1, "two", 3.0, "four") println("All String elements in upper case:") numbers.filterIsInstance<String>().forEach { println(it.uppercase()) } //sampleEnd }
  • filterNotNull() 函数返回不为 null 的元素. 对 List<T?> 调用这个函数时, filterNotNull() 返回的结果集合类型为 List<T: Any>, 因此你可以将结果集合的元素作为不为 null 的对象进行处理.

    fun main() { //sampleStart val numbers = listOf(null, "one", "two", null) numbers.filterNotNull().forEach { println(it.length) // 对于可为 null 的 String, length 属性是不可访问的 } //sampleEnd }

划分(Partition)

另一个过滤函数 – partition() – 根据一个判定条件过滤集合, 并把不满足判定条件的元素保存到另一个 list 中. 因此从返回值可以得到两个 List 构成的 Pair: 第一个 list 包含满足判定条件的元素, 第二个包含原集合中的所有其他元素.

fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") val (match, rest) = numbers.partition { it.length > 3 } println(match) println(rest) //sampleEnd }

验证判定条件

最后, 还有一些函数用来对集合验证某个判定条件:

  • any() 函数, 如果至少存在一个元素满足指定的判定条件, 则返回 true.

  • none() 函数, 如果不存在任何元素满足指定的判定条件, 则返回 true.

  • all() 函数, 如果所有的元素全部满足指定的判定条件, 则返回 true. 注意, 如果对空集合使用任何合法的判定条件调用 all(), 会返回 true. 这个结果在逻辑学上叫做 虚空真(vacuous truth).

fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") println(numbers.any { it.endsWith("e") }) println(numbers.none { it.endsWith("a") }) println(numbers.all { it.endsWith("e") }) println(emptyList<Int>().all { it > 5 }) // vacuous truth //sampleEnd }

any()none() 函数也可以不指定判定条件: 这种情况下它们只检查集合是否为空. 如果集合中存在元素, 则 any() 返回 true, 集合中没有元素, 则 false; none() 的返回值刚好与此相反.

fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") val empty = emptyList<String>() println(numbers.any()) println(empty.any()) println(numbers.none()) println(empty.none()) //sampleEnd }
最终更新: 2024/12/17