kotlin查漏补缺系列(不定期更新)
- Kotlin查漏补缺系列(1)—— 高阶函数
- Kotlin查漏补缺系列(2)—— 泛型
- Kotlin查漏补缺系列(3)—— 集合
前言
阅读本文需要你有一些java基础,至少已了解java集合的相关知识,耐心看完本文你将学会
- kotlin各种集合的使用
- kotlin集合和java集合的区别
- kotlin常用的集合操作符
有哪些集合类型
都知道java中集合主要包括三大类型,list,set以及map,在kotlin中也一样,集合的类图如下:
从这个类图,我们发现跟java相比,kotlin多了一些带Mutable前缀的接口或类,mutable是可变的意思, 很显然在kotlin中,集合被分成了两大类,可变集合和不可变集合,这也是kotlin与java的集合最大的不同
MutableList,MutableSet,MutableMap这些接口中提供了add,remove等方法,属于可变的集合接口
而List,Set,Map这些接口中不提供任何关于写入操作的方法,而且从接口的泛型声明上也能看到,使用了out(对泛型不太理解的可以看看之前写过的一篇关于泛型的文章),也表明他是只读的,属于不可变的集合接口
public interface List<out E> : Collection<E>
kotlin的集合怎么用
kotlin对集合的使用封装了大量的库函数,使用起来方便很多
List
创建一个不可变的list用listOf,可变的用mutableListof
// 不可变集合
val list1 = listOf(1,2,3)
// 可变集合
val list2 = mutableListOf(1,2,3)
上述创建的list1是不可变的,只能读,而读又有两种方式
// 推荐用这种,更简洁
val a = list1[1]
val b = list1.get(1)
list2是可变的,可以添加,删除数据
val list2 = mutableListOf(1,2,3)
list2.add(1)
list2.removeAt(1)
上面提到了不可变的List接口在泛型声明上使用了out,所以List是支持协变的,也就是可以把类型为子类的List赋值给类型是父类的List
val list1 = listOf(1,2,3)
val list2 : List<Any> = list1
Map
跟创建list一样,创建map也都是类似的库函数
val map1 = mapOf("key1" to 1,"key2" to 2)
val map2 = mutableMapOf("key1" to 1,"key2" to 2)
创建不可变的Map用maoOf,可变的用mutableMapOf,这里面有一点比较特殊的语法,创建的时候直接传入了键值对,"key1" to 1这样的写法表示一个key-value,其中to是中缀表达式(这个以后讲解),作用就是构造出一个Pair类型的数据,而Pair存储的就是键值数据
对于Map的写操作和读操作也跟java有些不一样
val map1 = mapOf("key1" to 1,"key2" to 2)
val map2 = mutableMapOf<String,Int>()
// 取值kotlin推荐用[],当然也可以用get
val a = map1["key1"]
// 写值kotlin也推荐用[],当然也可以用put
map2["key3"] = 3
这里set就不展开说了,跟list几乎一样,只不过它里面的数据是没有顺序,且不能重复的
集合的转换
通过listOf,mapOf等创建出来的不可变集合都可以通过toMutablexxx 方法复制出一个可变的集合
// 原来的list1还是不可变的,复制的list3就是可变的
val list3 = list1.toMutableList()
list3.add(1)
集合的迭代
kotlin中,集合的迭代一般有三种方式,迭代器,for循环,foreach
迭代器
kotlin的集合同样是实现了Iterable接口的,所以可以通过iterator接口获取到一个迭代器然后用hasNext迭代
val list1 = listOf(1,2,3)
val iterator = list1.iterator()
while (iterator.hasNext()){
println(iterator.next())
}
val map1 = mapOf("key1" to 1, "key2" to 2)
val iteratorMap = map1.iterator()
while (iteratorMap.hasNext()){
println(iteratorMap.next().value)
}
for循环
val list1 = listOf(1, 2, 3)
for (i in list1) {
println(i)
}
val map1 = mapOf("key1" to 1, "key2" to 2)
for (mapItem in map1) {
println(mapItem.value)
}
forEach扩展函数
kotlin为集合封装了很多扩展函数(也就是下面要讲的操作符),其中foreach用来循环遍历,可传入一个lambda表达式,表达式有一个参数表示当前遍历到的元素
val list1 = listOf(1, 2, 3)
list1.forEach {
println(it)
}
val map1 = mapOf("key1" to 1, "key2" to 2)
map1.forEach {
println(it.value)
}
集合的常用操作
kotlin的集合提供了非常多的操作符,需要的时候可以看看文档查一下,下面介绍下使用频率比较高的几个
元素操作符
例如获取元素,遍历元素
- contains():是否包含某元素
- first():获取第一个元素
- first{}:可传入一个lambda,指定满足条件的第一个元素
- last():获取最后一个元素
- last{}:可传入一个lambda,指定满足条件的最后一个元素
- forEach{}:遍历元素
- forEachIndexed{}:遍历元素,相比foreach,可以拿到元素索引
val list = listOf(1,2,3)
val isExist = list.contains(1)
val first = list.first()
val first1 = list.first { it > 1 }
val last = list.last()
val last1 = list.last { it > 1 }
list.forEach {
println(it)
}
list.forEachIndexed { index, item ->
println("index is $index,item is $item")
}
映射操作符
映射就是可批量对集合的元素进行相同的操作
- map{}:把每个元素按照特定逻辑进行转换,返回一个新的集合
- flatmap{}:利用集合的每个元素,生成一个新的集合,最终把所有集合合并为一个,有点儿绕是不是,看看demo
- group{}:对集合元素进行分组,返回一个Map,map中lambda的结果作为key,对应的item集合作为value
val list1 = listOf(1,2,3)
println(list1.map { it+1 })
// 运行结果
[2, 3, 4]
// flatmap
val list = listOf(listOf(1),listOf(2), listOf(3))
println(list)
// 其实可以直接用flatten实现这个效果,这个地方主要为了展示flatmap的作用
println(list.flatMap { it })
// 运行结果
[[1], [2], [3]]
[1, 2, 3]
//group
val list1 = listOf(1,2,3)
println(list1.groupBy { it>1 })
// 运行结果
{false=[1], true=[2, 3]}
过滤操作符
想取集合中部分子集的操作
- filter{}:按照给定的条件过滤集合中的元素,并返回所有满足条件的元素组成的新集合
- take():返回集合中前n个元素,同样的也有takeLast()
val list1 = listOf(1, 2, 3)
println(list1.filter { it > 1 })
// 运行结果
[2, 3]
println(list1.take(1))
// 运行结果
[1]
统计操作符
对集合中的元素按要求进行统计
- maxorNull():获取集合中最大的元素,如果集合为空,返回null
- any{}:判断集合是否存在元素满足条件
- all{}:判断集合中是否所有元素都满足条件
val list1 = listOf(1,2,3)
println(list1.maxOrNull())
println(list1.any { it > 2 })
println(list1.sum())
// 运行结果
3
true
6
以上只是列取了相对常见的一些集合操作符号,实际上kotlin提供的集合操作符还有很多很多,基本能满足绝大部份的开发需要
koltin的数组与java的区别
因为数组也是用来存储批量的数据,跟集合有很多相同的使用场景,而kotlin的数组和java的数组在使用上也有些差距,这里简单提一下
kotlin数组是Array类型的,它是一个泛型类,我们也可以通过库函数arrayOf来创建一个数组
val array = arrayOf(1,2,3)
如果存储的元素类型是Int这些原生类型,为了避免装箱的开销,kotlin还提供了各种原生类型的数组,例如IntArray,ByteArray
val intArray = intArrayOf(1,2,3)
val byteArray = byteArrayOf(1,2,3)
另外kotlin的数组和集合之间是可以互转的
val array = arrayOf(1,2,3)
val list = listOf(1,2,3)
val list1 = array.toList()
val array1 = list.toIntArray()
以上就是kotlin集合基础相关的分享,感谢您的阅读,欢迎评论交流