前言
重新梳理一遍关于集合的使用。
概述
集合是可变数量的一组条目。
- List : 是有序集合,可以通过下标访问元素,元素可以重复。
- Set : 是无序集合,有别于List集合的地方在于,1.没有下标,2.元素不允许重复。只能遍历获取参数,遍历参数的顺序与添加顺序相同。元素如果已经存在不进行添加。可以存储
Null
, 而且Null
也是唯一的。 - Map:是无序集合,通过键值对存储数据。每个键唯一。值可以重复。
所有的集合对象都是围绕着三种进行的扩展和定义。例如:ArrayList
,LinkedHashSet
,HashSet
,LinkedHashMap
,HashMap
构造集合
创建一个普通的集合:
代码语言:javascript复制fun main(array: Array<String>) {
//创建的集合不允许添加
//创建一个List对象
var list = listOf("A", "B", "C")
//创建一个 set 对象
var set = setOf("A", "B", "C")
//创建一个map 对象
var map = mapOf<String, Int>("A" to 1, "B" to 2, "C" to 3)
//创建集合允许修改
var list1 = mutableListOf("A", "B", "C")
var set1 = mutableSetOf("A", "B", "C")
var map1 = mutableMapOf<String, Int>("A" to 1, "B" to 2, "C" to 3)
}
其中在创建Map对象时, to
会创建短时存活的Pair对象。带来额外的内存开销。
如果要优化,可以使用apply()
函数
//to 会创建短时存活的Pair对象。建议替换入下
var map2 = mutableMapOf<String, Int>().apply {
this["A"] = 1
this["B"] = 2
this["C"] = 3
}
创建空集合
代码语言:javascript复制//创建空集合. 如果不加上toMotableXXX()函数,那么这个集合将没有修改接口使用
var list3 = emptyList<String>().toMutableList()
var map3 = emptyMap<String, Int>().toMutableMap()
var set3 = emptySet<String>().toMutableSet()
不使用Kotlin提供的全句函数,创建集合:
代码语言:javascript复制fun main(string: Array<String>) {
var linkedList = LinkedList<String>()
linkedList.add("LinkedList-String")
linkedList.add("zin")
linkedList.add("yan")
println(linkedList)
var arrayList = ArrayList<String>()
arrayList.add("ArrayList-String")
arrayList.add("zin")
arrayList.add("yan")
println(arrayList)
}
Set
和Map
也有类似的实现
复制
kotlin之中也分为深复制和浅复制。
在系统提供的函数中,已经封装了 toList()
,toMutableList()
,toArray()
,toMap
等方法。
可以直接复制一个新的集合对象出来。旧集合发生变化。不影响新集合。
实例1:
代码语言:javascript复制var linkedList = LinkedList<String>()
linkedList.add("LinkedList-String")
linkedList.add("zin")
linkedList.add("yan")
var arrayList = linkedList.toList()
linkedList.add("url")
println(linkedList)
println(arrayList)
//输出
[LinkedList-String, zin, yan, url]
[LinkedList-String, zin, yan]
其中Set 和Map 也有相同的方法。可以方便我们进行数组的复制。
实例2:
代码语言:javascript复制var ss = 123
var linkedList = LinkedList<Any>()
linkedList.add("LinkedList-String")
linkedList.add("zin")
linkedList.add(ss)
var arrayList = linkedList.toList()
ss = 231
linkedList.add("url")
println(linkedList)
println(arrayList)
//输出
[LinkedList-String, zin, 123, url]
[LinkedList-String, zin, 123]
我们可以发现,集合里面的对象发生了变化,而两个集合没有变化。
那么我们如果需要浅拷贝该如何处理?
直接通过等号复制即可
代码语言:javascript复制var linkedList = LinkedList<Any>()
linkedList.add("LinkedList-String")
linkedList.add("zin")
var arrayList = listOf<Any>()
arrayList = linkedList
linkedList.add("Url")
println(linkedList)
println(arrayList)
//输出
[LinkedList-String, zin, Url]
[LinkedList-String, zin, Url]
同时,我们可以在复制的时候 直接将list
改为set
或 Array
。反之也是一样的。
var linkedList = LinkedList<Any>()
linkedList.add("LinkedList-String")
linkedList.add("zin")
var arrayList = linkedList.toArray()
var setList = linkedList.toSet()
同时我们在复制的时候,也可以改变集合对象的可变性。
例如将List
改为MutableList
等等。
我们通过集合的 filter
函数,map
函数,accociate
函数等输出的结果集也是一个独立对象
实例1:
代码语言:javascript复制 var word = listOf<String>("aaa", "bbb", "cccc", "dddd")
var tesp = word.filter {
it.length > 3
}
println(tesp)
//输出
[cccc, dddd]
过滤器的结果,将会自动生成一个新的集合对象。
修改新的集合对象参数,不影响源集合对象参数。
迭代器 iterator
实例
代码语言:javascript复制var word = mutableListOf("aaa", "bbb", "cccc", "dddd")
var iterator = word.iterator()
while (iterator.hasNext()) {
var s = iterator.next()
println(s)
}
//输出
aaa
bbb
cccc
dddd
上面的方法与for 循环其实是等效的。for允许隐式获取了迭代器
实例:
代码语言:javascript复制for(i in word){
println(i)
}
forEach()函数
代码语言:javascript复制var word = mutableListOf("aaa", "bbb", "cccc", "dddd")
word.forEach {
//根据item 判断执行的函数
if (it.length > 3) {
println(it)
}
}
List 迭代器
在Kotlin的标准库中,针对List 还提供了一个ListIterator
迭代器。我们上面的迭代都是从小到大。
而ListIterator
支持双向迭代,可以从小到大也可以从大到小。
与之对应的方法:
hasPrevious()
与 hasNext()
。
previous()
与 next()
。
previousIndex()
与 nextIndex()
。
实例:
代码语言:javascript复制fun main(string: Array<String>) {
var word = listOf("A","C","B")
val listinterator = word.listIterator()
println("正序")
while (listinterator.hasNext()) {
println("下标值:${listinterator.nextIndex()}")
println(listinterator.next())
}
println("倒序")
while (listinterator.hasPrevious()){
println("下标值:${listinterator.previousIndex()}")
println(listinterator.previous())
}
}
//输出
正序
下标值:0
A
下标值:1
C
下标值:2
B
倒序
下标值:2
B
下标值:1
C
下标值:0
A
可以通过previousIndex()
与 nextIndex()
获取到当前对象的index 下标值。
注意:迭代器只有从正到反,然后才能从反到正。循环一遍之后,再重新从大到小需要重新获取迭代器。
可变迭代器
在java中如果遍历数组时,执行删除会出现迭代器越界崩溃的异常。
而针对遍历删除的需求,在开发中又是比较常用的功能特性。所以kotlin之中针对该需求,有了一个MutableIterator
迭代器。来实现在迭代时针对集合的删除功能。
实例:
代码语言:javascript复制fun main(string: Array<String>) {
//创建一个可变List 集合对象,
var numbers = mutableListOf("A", "B", "C", "D", "E")
//获取集合对象的 迭代器
var iterator = numbers.listIterator()
println("删除之前的结果:$numbers")
while (iterator.hasNext()) {
val index = iterator.nextIndex();
println("下标值:$index")
if(index==2){
iterator.remove()
println("删除")
}else {
println(iterator.next())
}
}
println("删除之后的结果:$numbers")
}
//输出结果
删除之前的结果:[A, B, C, D, E]
下标值:0
A
下标值:1
B
下标值:2
删除
下标值:1
C
下标值:2
删除
下标值:1
D
下标值:2
删除
下标值:1
E
删除之后的结果:[A, E]
除了remove()
删除方法还有add()
添加方法和set()
修改方法
实例2:
代码语言:javascript复制fun main(string: Array<String>) {
//创建一个可变List 集合对象,
var numbers = mutableListOf("A", "B", "C", "D", "E")
//获取集合对象的 迭代器
var iterator = numbers.iterator()
println("删除前的结果:$numbers")
iterator.next()
iterator.remove()// 删除
println("删除后的结果:$numbers")
//添加 如果是添加和修改 需要获取list 对象
var listiterator= numbers.listIterator()
listiterator.next()
listiterator.add("ZINYAN")
listiterator.next()
listiterator.set("Zin")
println("修改和添加后的结果:$numbers")
}
//输出
删除前的结果:[A, B, C, D, E]
删除后的结果:[B, C, D, E]
修改和添加后的结果:[B, ZINYAN, Zin, D, E]
字符串输出 joinToString
针对集合,我们可以使用joinToString 将集合对象直接转为String字符串
示例1:
代码语言:javascript复制fun main(string: Array<String>) {
val s = listOf("A", "B", "C", "D", "E", "F")
println(s)
println(s.joinToString())
}
//输出
[A, B, C, D, E, F]
A, B, C, D, E, F
示例2:
可以将数组集合对象输出成字符串,拼接到指定字符串的后面
代码语言:javascript复制fun main(string: Array<String>) {
val s = listOf("A", "B", "C", "D", "E", "F")
val listString = StringBuffer("这个集合数据信息:")
s.joinTo(listString)
println(listString)
}
//输出
这个集合数据信息:A, B, C, D, E, F
针对List 数据过大的,我们想指定显示的数量
示例3:
代码语言:javascript复制fun main(string: Array<String>) {
//我们将一个区间数据 转为List 对象
val number = (1..100).toList()
println(number.joinToString(limit = 10, truncated = "..."))
}
//输出
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
limit定义了list 的显示长度,如果超过,就将使用truncated 定义的字符进行替换。我们可以自定义替换的字符。
如果你觉得中间的默认分割符不好也可以自定义:separator 参数
示例4:
代码语言:javascript复制println(number.joinToString(limit = 10, truncated = "...",separator = "_"))
//输出
1_2_3_4_5_6_7_8_9_10_...
我们如果想给输出的字符串添加开头和后缀,可以自定义:prefix参数,postfix参数。
示例5:
代码语言:javascript复制println(number.joinToString(limit = 10, truncated = "...",separator = "_",prefix="开始",postfix = "结束"))
//输出
开始1_2_3_4_5_6_7_8_9_10_...结束
我们如果针对输出结果,也可以做一些格式化处理,通过自定义:transform参数
示例6:
代码语言:javascript复制val number = (1..100).toList()
println(
number.joinToString(
limit = 10,
truncated = "...",
separator = "_",
prefix = "开始",
postfix = "结束",
transform = {
"V=${it 1}"
})
)
//输出
开始V=2_V=3_V=4_V=5_V=6_V=7_V=8_V=9_V=10_V=11_...结束
集合元素的增删改操作
add和addAll() 添加
上面其实也已经介绍了集合的添加。下面只是简单介绍一下。
add() :
将单个元素添加到集合中。addAll():
将多个元素添加到集合中。参数是:Iterable,Sequence,Array,List等
示例1:
代码语言:javascript复制fun main(string: Array<String>) {
val numbers = mutableListOf(1, 2, 3, 4)
numbers.add(5)
println(numbers)
}
//输出
[1, 2, 3, 4, 5]
示例2:
代码语言:javascript复制fun main(string: Array<String>) {
val numbers = mutableListOf(1, 2, 5, 6)
numbers.addAll(arrayOf(7, 8))
println(numbers)
numbers.addAll(2, setOf(3, 4))
println(numbers)
}
//输出
[1, 2, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
remove() ,retainAll(),clear() 删除集合元素
示例:移除元素
代码语言:javascript复制fun main(string: Array<String>) {
val numbers = mutableListOf(1, 2, 5, 6)
numbers.remove(1)
println(numbers)
}
//输出
[2, 5, 6]
注意,这几个参数都不是删除集合对象,而是针对集合内部元素进行的清理操作。
几个删除方法的介绍:
remove():
移除指定的元素对象。如果指定元素不存在,移除null。不会报错removeAll():
移除参数集合中存在的所有元素。或者,你可以关键字作为参数来调用它;在这种情况下,函数移除关键字匹配true
的所有元素。retainAll()
与removeAll()
相反:它移除除参数集合中的元素之外的所有元素。当与关键字一起使用时,它只留下与关键字匹配的元素。clear()
从列表中移除所有元素并将其置空。
示例:
代码语言:javascript复制fun main(string: Array<String>) {
val numbers = mutableListOf(1, 2, 3, 4)
println(numbers)
numbers.retainAll { it >= 3 }
println(numbers)
numbers.clear()
println(numbers)
val numbersSet = mutableSetOf("one", "two", "three", "four")
numbersSet.removeAll(setOf("one", "two"))
println(numbersSet)
}
//输出
[1, 2, 3, 4]
[3, 4]
[]
[three, four]
还有一种扩展和简单使用方法,就是使用操作符。
在 Kotlin集合-plus,minus和分组group详解 - Z同学 (zinyan.com) 有相关介绍。可以参考
更新 set() 和fill()
如果要修改指定下标位置的元素和数组的修改是类似的。
示例:
代码语言:javascript复制fun main(string: Array<String>) {
val numbers = mutableListOf("one", "two", "three", "four")
numbers[1]="AAA"
println(numbers)
}
//输出
[one, AAA, three, four]
其实,该方式就是 set()
的操作符形式[]
fill:可以将所有集合元素的值替换为指定值。
示例:
代码语言:javascript复制fun main(string: Array<String>) {
val numbers = mutableListOf("one", "two", "three", "four")
numbers.fill("Zinyan")
println(numbers)
}
//输出
[Zinyan, Zinyan, Zinyan, Zinyan]