过滤(Filtering)集合
在对集合的处理中, 过滤是最常见的任务之一. Kotlin 中, 过滤条件使用 判定条件(predicate) 来表示 – 它是一个 lambda 函数, 接受的参数是集合元素, 返回结果是布尔值: true
代表这个元素满足判定条件, false
表示不满足判定条件.
标准库提供了一组扩展函数, 你可以只通过一次函数调用就能过滤集合. 这些函数不修改原来的集合, 因此对 可变集合和只读集合 都可以使用. 要操作过滤后的结果集合, 你应该将它赋值给一个变量, 或者在过滤之后链式调用其他函数.
使用判定条件进行过滤
最基本的过滤函数是 filter()
. 调用这个函数时使用判定条件作为参数, filter()
函数会返回集合中满足这个判定条件的元素. 对于 List
和 Set
, 结果集合都是 List
, 对于 Map
, 结果集合也是 Map
.
在 filter()
函数的判定条件中, 只能检查元素的值. 如果在过滤时还想使用元素的位置, 请使用 filterIndexed()
函数. 这个函数的判定条件接受两个参数: 第一个是元素下标, 第二个是元素值.
如果要按照相反的条件来过滤集合, 请使用 filterNot()
函数. 它返回判定条件结果为 false
的元素.
还有一些函数, 可以根据元素的类型进行过滤, 得到元素类型缩窄后的集合:
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 包含满足判定条件的元素, 第二个包含原集合中的所有其他元素.
验证判定条件
最后, 还有一些函数用来对集合验证某个判定条件:
any()
函数, 如果至少存在一个元素满足指定的判定条件, 则返回true
.none()
函数, 如果不存在任何元素满足指定的判定条件, 则返回true
.all()
函数, 如果所有的元素全部满足指定的判定条件, 则返回true
. 注意, 如果对空集合使用任何合法的判定条件调用all()
, 会返回true
. 这个结果在逻辑学上叫做 虚空真(vacuous truth).
any()
和 none()
函数也可以不指定判定条件: 这种情况下它们只检查集合是否为空. 如果集合中存在元素, 则 any()
返回 true
, 集合中没有元素, 则 false
; none()
的返回值刚好与此相反.