🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ### list集合介绍 list集合怎么定义呢?从概念角度去理解,list集合也叫list列表,存储的元素有序可重复。有序,就是存储的位置是固定的,谁先存储顺序就越靠前;可重复,可以存储重复数据;从代码角度去理解, list由List接口和List接口的实现类组成。 List接口常用的实现类有哪些? ArrayList、LinkedList和MutableList。kotlin中只有ArrayList和MutableList list集合可以存储什么类型数据呢? list集合可以存储各种类型数据。可以存储诸如Int、Double、String等基本数据类型,也可以存储其他自定义对象类型,比如自定义的学生Student。 ### list集合4种创建方式 在Kotlin中创建list集合有4种方式,4种方式可以分为两类,一类是通过构造方法方法创建list集合。另外一种,是通过Kotlin给我们封装好的方法创建list集合。如下表格,我们将这四种方式列举了出来。 | **创建list集合方法** | **返回值类型** | **是否可写** | | ----------------------------- | ------------- | ------------ | | **通过List构造方法创建** | List | 否 | | **listOf()方法** | List | 否 | | **arrayListOf()方法** | ArrayList | 是 | | **mutableListOf()方法** | MutableList | 是 | 我们可以直接看4种方式的对应方法的方法签名,重点看返回值,方法体的部分我直接去掉了,对应的源码如下: ``` public inline fun<T> List(size:Int,init:(index:Int)->T):List<T>{} public fun<T> listOf(vararg element:T):List<T>{} public fun arrayListOf(vararg element:T):ArrayList<T>{} public fun <T> mutableListOf(vararg elements: T):MutableList<T>{} ``` 可以通过翻看源码得知4种创建集合方式上的细微差别,有的是通过Java里面的ArrayList创建,有的是通过asList方法转换为的集合。这个意义不是很大。 更重要的需要知道,通过List接口构造方法和listOf方法创建的集合是不可写的,通过arrayListOf方法和mutableListOf方法创建的集合是可写的。具体使用的时候,忘记是否可写怎么办?只需要点进去看看方法的返回值即可,返回List不可写,返回ArrayList、MutableList则可写。或者,看每个方法的注释,返回只读的list集合,会出现“**read-only** **list**”字样。比如看List接口构造方法创建集合的注释: ![](http://upload-images.jianshu.io/upload_images/7368752-d4bbeba8645af389.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 还有就是,如何集合元素很有规律的时候,用List的构造方法创建,比如元素是[1,2,3、4]、[1,2,4,8] 、[1,3,6,9]。listOf方法、arrayListOf方法、mutableListOf方法,创建集合的时候只需要往里面扔具体的元素就可以了。 我们通过代码演示集合的四种创建方式: ~~~ fun main(args: Array<String>) { val list = List(3, { it * 2 }) println(list) val list1 = listOf("a", "b", "c") println(list1) val list2 = arrayListOf(1, 2, 3) println(list2) val list3 = mutableListOf("a", "b", 'c', 5) println(list3) } ~~~ 运行结果 ``` [0, 2, 4] [a, b, c] [1, 2, 3] [a, b, c, 5] Process finished with exit code 0 ``` 针对以上代码难理解一点的可能就是第2行,通过List接口构造方法创建list集合,这里涉及到了Lambda表达式。这个可以稍微放一放,学习完Lambda表达式之后在回过头来看。并且,确实,这种创建方式用的相对较少。 ### List集合的可写性验证以及转换 我们通过代码验证集合是否可写,先验证集合可写,参考代码: ~~~ fun main(args: Array<String>) { val list2 = arrayListOf(1, 2, 3) //可写性 list2.add(4) println(list2) val list3 = mutableListOf("a", "b", 'c', 5) //可写性 list3.add(18.4) println(list3) } ~~~ 运行结果 ``` [1, 2, 3, 4] [a, b, c, 5, 18.4] Process finished with exit code 0 ``` 我们再验证集合不可写,参考代码: ![](http://upload-images.jianshu.io/upload_images/7368752-23ae5d170975c101.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 但是,不可写集合可以通过totoMutableList转换为可写集合,然后在进行写操作,参考代码: ~~~ fun main(args: Array<String>) { val list: List<Int> = List(3, { it * 2 }) println("转换前的list:$list") //转换添加 list.toMutableList().add(4)//转换为可写的list println("转换后的新的list:$list") println("---------注意下面的添加方式与上面的不同之处-----------") val newList = list.toMutableList() println("已转换的未进行可写操作的newList:$newList") newList.add(5) println("已转换的进行可写操作后的newList:$newList") println("--------------------------------------------------------") val list1 = listOf("a", "b", "c") println("转换前的list1:$list1") list1.toMutableList().add("d") println("转换后的新的list1:$list1") println("---------注意下面的添加方式与上面的不同之处-----------") val newList1 = list1.toMutableList() println("已转换的未进行可写操作的newList1:$newList1") newList1.add("d") println("已转换的进行可写操作后的newList1:$newList1") } ~~~ 运行结果 ``` 转换前的list:[0, 2, 4] 转换后的新的list:[0, 2, 4] ---------注意下面的添加方式与上面的不同之处----------- 已转换的未进行可写操作的newList:[0, 2, 4] 已转换的进行可写操作后的newList:[0, 2, 4, 5] -------------------------------------------------------- 转换前的list1:[a, b, c] 转换后的新的list1:[a, b, c] ---------注意下面的添加方式与上面的不同之处----------- 已转换的未进行可写操作的newList1:[a, b, c] 已转换的进行可写操作后的newList1:[a, b, c, d] Process finished with exit code 0 ``` * [ ] **疑问**:注意以下代码的不同之处 ~~~ val list: List<Int> = List(3, { it * 2 }) //转换添加 list.toMutableList().add(4)//转换为可写的list println(list)//[0, 2, 4] val newList = list.toMutableList() newList.add(5) println(list)//[0, 2, 4, 5] ~~~ 为什么会有截然不同的两种结果? >[success]**注意**:之所以出现两种结果,是因为执行完`list.toMutableList()`后,生成的新的List,原List没有变化!而且add方法的返回值是一个Boolean类型,所以`println(list)//[0, 2, 4]`,结果还是原来的list,而经过下面的代码`val newList = list.toMutableList()`已经生成一个新的list,执行`newList.add(5)`,就是一个正常的写入的过程,自然就得到`println(list)//[0, 2, 4, 5]` ### list集合数据可重复 list集合中的元素可重复,是list相对于set的一个重要特点。同时,**list集合中可以存储null元素**,我们通过一个案例验证下list集合可以包含重复代码,参考代码: ![](http://upload-images.jianshu.io/upload_images/7368752-47372c2091f70b58.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ### list集合遍历 前面我们学习了区间的遍历,数组的遍历。那如何遍历list集合呢?list集合的遍历和数组的遍历一样。 也就是list集合在遍历的时候,可以普通的for循环,还可以for循环的时候调用withIndex方法,参考代码: ~~~ fun main(args: Array<String>) { val list = mutableListOf(1, 2, 3, 4, 5) println("---------普通for循环遍历-----------") for (c in list) { println(c) } println("---------for循环 withIndex遍历-----------") for (withIndex in list.withIndex()) { println("${withIndex.index} -> ${withIndex.value}") } println("---------for循环 解析析构遍历-----------") for ((index, value) in list.withIndex()) { println("${index} -> ${value}") } } ~~~ 运行结果 ``` ---------普通for循环遍历----------- 1 2 3 4 5 ---------for循环 withIndex遍历----------- 0 -> 1 1 -> 2 2 -> 3 3 -> 4 4 -> 5 ---------for循环 解析析构遍历----------- 0 -> 1 1 -> 2 2 -> 3 3 -> 4 4 -> 5 Process finished with exit code 0 ``` 当然,还可以通过迭代器以及高阶函数进行遍历操作, 比如 #### 集合list迭代器遍历 ``` fun main(args: Array<String>) { val list: List<Int> = listOf(1, 2, 3, 4) val iterator1 = list.listIterator() //获取一个集合的迭代器 val iterator2 = list.listIterator(1) //获取从索引位置1开始的集合的迭代器 println("遍历集合中的元素:") while (iterator1.hasNext()) { print(iterator1.next().toString() + "\t") } println("\n" + "从索引1开始遍历集合中的元素:") while (iterator2.hasNext()) { print(iterator2.next().toString() + "\t") } } ``` 运算结果 ``` 遍历集合中的元素: 1 2 3 4 从索引1开始遍历集合中的元素: 2 3 4 ``` #### 集合MutableList迭代器遍历 ``` fun main(args: Array<String>) { val muList: MutableList<String> = mutableListOf("春天", "夏天", "秋天", "冬天") val iterator1 = muList.listIterator() //获取集合的迭代器 val iterator2 = muList.listIterator(1) //获取从位置1开始的集合的迭代器 println("遍历集合中的元素:") while (iterator1.hasNext()) { print(iterator1.next() + "\t") } println("\n" + "从索引为1处开始遍历集合中的元素:") while (iterator2.hasNext()) { print(iterator2.next() + "\t") } } ``` 运行结果 ``` 遍历集合中的元素: 春天 夏天 秋天 冬天 从索引为1处开始遍历集合中的元素: 夏天 秋天 冬天 ```