Kotlin 集合 基础介绍

2023-07-13 16:08:38 浏览数 (1)

前言

重新梳理一遍关于集合的使用。

概述

集合是可变数量的一组条目。

  • 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()函数

代码语言:javascript复制
//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)
}

SetMap 也有类似的实现

复制

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 改为setArray。反之也是一样的。

代码语言:javascript复制
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]

0 人点赞