作为一名前Java开发者,当我每次需要写一些冗长且常用的功能时,时常会发出这样的感叹:
这个功能JDK中怎么没有啊?每次都要写好几十行代码,JDK不应该把这个功能封装一下吗
不知道广大的Java开发者是否也会跟我一样,也会有类似的感慨,欢迎大家留言讨论。
在用了Kotlin之后,才知道什么才是真正的方便,其针对集合做了非常丰富的支持:排序、查询、条件过滤、类型转换等等,本文就盘点一下Kotlin中集合的一些骚操作。
Kotlin 标准库提供了 set
、list
以及 map
的实现。与 Java 不同的是,Kotlin对集合做了区分:元素是否可变,可变的容器会加Mutable
前缀,实现对应的接口:
一个 只读 接口,只提供访问集合元素的操作。
一个 可变 接口,通过写操作扩展相应的只读接口:添加、删除及更新其元素。
Kotlin中Collection
的结构如下:
每种容器类型都有可变与不可变之分,可变的是不可变的子类,如:
MutableCollection
会实现对应的Collection
接口(如下图)
集合的高阶操作大致可分为六类:
元素操作符
顺序操作符
映射操作符
过滤操作符
生产操作符
统计操作符
componentX()
:获取集合中的某一个元素,其中的X
只能取1..5
,其是List
的扩展函数
contains(element: T)
: 集合中是否包含指定的元素,若存在则返回true
,反之返回false
elementAt(index: Int)
: 获取对应下标的元素。若下标越界,会抛出IndexOutOfBoundsException(下标越界)
异常,与get(index)
一样
elementAtOrElse(index: Int, defaultValue: (Int) -> T)
: 获取对应下标的元素。若下标越界,返回默认值,此默认值就是你传入的下标的运算值
elementAtOrNull(index)
: 获取对应下标的元素。若下标越界,返回null
first()
: 获取第一个元素,若集合为空集合,这会抛出NoSuchElementException
异常
first{}
: 获取满足条件的第一个元素。若不满足条件,则抛出NoSuchElementException
异常
firstOrNull()
: 获取第一个元素,若集合为空集合,返回null
firstOrNull{}
: 获取满足条件的第一个元素。若不满足条件,返回null
getOrElse(index,{...})
: 同elementAtOrElse
getOrNull(index)
: 同elementAtOrNull
last()
: 与first()
相反
last{}
: 与first{}
相反
lastOrNull{}
: 与firstOrNull()
相反
lastOrNull()
: 与firstOrNull{}
相反
indexOf(T)
: 返回指定元素的下标,若不存在,则返回-1
indexOfFirst{...}
: 返回第一个满足条件元素的下标,若不存在,则返回-1
indexOfLast{...}
: 返回最后一个满足条件元素的下标,若不存在,则返回-1
single()
: 若集合的长度等于0
,则抛出NoSuchElementException
异常,若等于1
,则返回第一个元素。反之,则抛出IllegalArgumentException
异常
single{}
: 找到集合中所有满足条件的元素,若找到的元素个数为1,则返回该元素。否则会根据不同的条件,抛出异常(与singel()
一致)
singleOrNull()
: 与single()
类似,但不会抛出异常,会返回null
singleOrNull{}
: 与single{}
类似,但不会抛出异常,会返回null
forEach{...}
: 遍历元素本身
forEachIndexed{index,value}
: 遍历下标及元素
看到这里,你是不是想说,Kotlin就这?
稍安勿躁!
接着往下看~
reversed()
: 反转集合。
sorted()
: 自然升序。
sortedBy{}
: 有条件的升序(不满足条件的放在前面,满足条件的放在后面)
sortedDescending()
: 自然降序。
sortedByDescending{}
: 有条件的降序(不满足条件的放在后面,满足条件的放在前面),与sortedBy{}
相反
sortedWith(comparator:
Comparator``<``in
T)
:自定义比较器
map{...}
: 把每个元素按照特定的方法进行转换,组成一个新的集合
mapNotNull{...}
: 与map{}
函数的作用相同,但会过滤掉转换之后为null
的元素
mapIndexed{index,result}
: 与map{}
函数的作用相似,但在转换过程中可以拿到每个元素的下标,最终也会组成一个新的集合
mapIndexedNotNull{index,result}
: 与mapIndexed{}
函数的作用相同,但会过滤掉转换之后为null
的元素
<T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R>
: 可分为flat和map两个步骤,flat可以将集合扁平化处理,map可以对集合进行转换。该函数在处理集合嵌套层级很多的情况很实用,可以很大程度上简化操作
<T, K> Iterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>>
: 对集合进行分组。你需要传一个key,函数会根据条件把集合拆分为为一个Map<K,List<T>>
类型的集合
示例:
`val numbers = listOf(1, 2, 3, 4) val squared = numbers.map { it * it } // squared 是 [1, 4, 9, 16],每个数字被平方 val mixedValues = listOf("1", "two", "3", "four") val integers = mixedValues.mapNotNull { it.toIntOrNull() } // integers 是 [1, 3],只有可以转换为整数的字符串被保留 val words = listOf("apple", "banana", "cherry") val indexedWords = words.mapIndexed { index, word -> "$index: $word" } // indexedWords 是 ["0: apple", "1: banana", "2: cherry"],每个单词前加上了它的索引 val data = listOf("some", "", "text", "none", "here") val nonEmptyItems = data.mapIndexedNotNull { _, value -> if (value.isNotBlank()) value else null } // nonEmptyItems 是 ["some", "text", "none", "here"],过滤掉了空字符串 val nestedLists = listOf(listOf(1, 2), listOf(3), listOf(4, 5, 6)) val flatList = nestedLists.flatMap { it } // flatList 是 [1, 2, 3, 4, 5, 6],将嵌套的列表展平 val people = listOf("Alice", "Bob", "Charlie", "David", "Eve") val byFirstLetter = people.groupBy { it.first() } // byFirstLetter 是 {'A'=["Alice"], 'B'=["Bob"], 'C'=["Charlie"], 'D'=["David"], 'E'=["Eve"]},按名字首字母分组 `
到此,阁下该如何应对?
篇幅太长,下一章讲集合的过滤操作符、生产操作符及统计操作符。