kotlin集合操作——list set map

简述

  kotlin有三个集合类型——list set map,kotlin标准库提供了一整套用于管理集合的工具

  这些集合接口与相关函数位于 kotlin.collections 包中

  kotlin的集合分为可变集合类Mutable和不可变集合类Immutable,List、Set、Map都是不可变集合,与之对应MutableList、MutableSet、MutableMap是可变集合

创建集合

  使用 listOf()、setOf()、mapOf() 创建不可变的 List、Set、Map

  使用 mutableListOf()、mutableSetOf()、mutableMap() 创建可变的 MutableList 、MutableSet 、MutableMap

  注意这里的to代表连接一个键值对,to前面是键,后面是值,set的默认实现是 LinkedHashSet

val list = listOf(1, 2, 3, 4, 5) 
val mutableList = mutableListOf("a", "b", "c")  

val set = setOf(1, 2, 3, 4, 5)
val mutableSet = mutableSetOf("a", "b", "c") 

val map = mapOf(1 to "a", 2 to "b", 3 to "c")
val mutableMap = mutableMapOf(1 to "X", 2 to "Y", 3 to "Z")

遍历集合

  我们可以使用forEach遍历集合,其中map的遍历可通过it.key和it.value来获取键和值

list.forEach {
     println(it)
}

set.forEach {
     println(it)
}

map.forEach {
     println("K = ${it.key}, V = ${it.value}")
}

  若想在遍历的同时获取当前元素的下标,我们可以使用forEachIndexed方法

list.forEachIndexed { index, value -> 
     println("list index = ${index}, value = $value")
}

set.forEachIndexed { index, value ->
    println("set index = ${index}, value = ${value}")
}

添加元素

  对于list,我们可以使用add方法添加元素,参数为一个时往list的末尾添加,两个参数时为往指定的index添加

val list = mutableListOf<Number>(1,2,3)
list.add(4)
list.forEach {
    print("$it ") // 1 2 3 4
}
println()
list.add(3,-1)
list.forEach {
    print("$it ") // 1 2 3 -1 4
}

  对于set,使用add方法添加元素,注意set是去重的

val set = mutableSetOf<Number>(1,2,3)
set.add(4)
set.forEach{
    println(it)
}

  对于map,可以使用put方法添加,更常见的是使用中括号+等于的形式,括号内是键名,等号是值

val map = mutableMapOf<Number,String>(1 to "a",2 to "b")
//map.put(3,"c")
map[3]="c"
map.forEach{
    println("${it.key}  ${it.value}")
}

删除元素

  list使用remove(value)删除值为value的元素,使用removeAt(index)删除指定下标元素

  removeFirst()和removeLast()删除第一个和最后一个元素

val list = mutableListOf<Number>(10, 20, 30, 40, 50, 60, 70)
list.remove(10) //  20, 30, 40, 50, 60, 70
list.removeAt(2) //  20, 30, 50, 60, 70
list.removeFirst() // 30, 50, 60, 70
list.removeLast() // 30, 50, 60

  set的remove删除指定值的元素

val set = mutableSetOf<Number>(10, 20, 30, 40)
set.remove(20) // 10 30 40

  map使用remove删除元素,remove传入想删除的键值

val map = mutableMapOf<Number,String>(1 to "a",2 to "b")
map.remove(2)
map.forEach{
    println("${it.key} ${it.value}") // 1 a
}

list集合相关操作

按索引取元素

  list本质就可以理解为一个变长数组,最简单的就是像数组一样通过[]拿到值

val numbers = listOf(1, 2, 3, 4)
println(numbers.get(0))
println(numbers[0])
//numbers.get(5)                         // exception!
println(numbers.getOrNull(5))             // null
println(numbers.getOrElse(5, {it}))        // 5

取列表的一部分

  使用subList可以指定左闭右开的区间,取出list的一部分

val numbers = (0..13).toList()
println(numbers.subList(3, 6))

排序

  对于普通的基本类型,可以直接调用sort()和sortDescending()进行升序和降序排列

val list = mutableListOf(5,4,1,2,3,7,10)
list.sort() //按升序排序
list.sortDescending() //降序

  sort()和sortDescending()加上ed变成sorted()和sortedDescending()则是返回一个全新的排序后的list,原来的list不变

  我们还可以使用sortBy()方法进行排序,例如这里我们对Student类的age属性进行生序排序

  sortBy是以值的自然顺序进行排序,Int、Double、String等都都定义好的自然顺序

data class Student(
    val age: Int,
    val name: String,
)

fun main() {
    val students = mutableListOf<Student>(
        Student(12, "c"),
        Student(19, "b"),
        Student(15, "a")
    )
    students.sortBy { x -> x.age }
    students.forEach(::println)
}

  同理sortByDescending是根据降序的自然顺序排序

sortWith

  查看sortBy的源码我们可以看到内部调用的是sortWith,sortWith常用于根据不同条件进行排序

  sortWith需要传入一个比较器Comparator参数,我们可以用compareBy生成自己想要的比较器

  compareBy里面靠左的优先级高,默认是升序排序,例如这里我们先通过age升序排序,age相同时根据name升序排序

data class Student(
    val age: Int,
    val name: String,
)

fun main() {
    val students = mutableListOf<Student>(
        Student(12, "c"),
        Student(19, "b"),
        Student(19, "a"),
        Student(15, "a"),
    )
    students.sortWith(compareBy({ it.age }, { it.name }))
    students.forEach(::println)
}

  如果需要先a属性升序,再b属性降序排序,则在生成的comparator后使用thenByDescending指定属性进行降序排序

data class Student(
    val age: Int,
    val name: String,
)

fun main() {
    val students = mutableListOf<Student>(
        Student(12, "c"),
        Student(19, "b"),
        Student(19, "a"),
        Student(15, "a"),
    )
    students.sortWith(compareBy<Student> { it.age } .thenByDescending { it.name })
    students.forEach(::println)
}

  同理可以无限套娃下去,这里的例子是先根据age升序,再根据name降序,再根据bAge升序

data class Student(
    val age: Int,
    val name: String,
    val bAge: Int,
)

fun main() {
    val students = mutableListOf<Student>(
        Student(12, "c",5),
        Student(19, "b",3),
        Student(19, "a",4),
        Student(19, "a",2),
        Student(15, "a",2),
    )
    students.sortWith(compareBy<Student> { it.age }.thenByDescending { it.name }.thenBy { it.bAge })
    students.forEach(::println)
}

GroupBy转map

  对于一个对象list,我们可以根据对象的属性将list分组,和数据库的groupBy类似

  例如我们这里有一个student的list

val students = mutableListOf<Student>(
    Student(1, "xiaoming", "guangzhou"),
    Student(2, "xiaohong", "shenzhen"),
    Student(2, "xiaohong2", "shenzhen"),
    Student(2, "xiaohong3", "chongqing"),
    Student(3, "xiaohei", "xian"),
    Student(3, "xiaohei2", "shenzhen"),
)

  然后我们可以通过student的age进行分组,分组后list会变成一个map,key是我们分组的属性,value是一个list,装着所有符合该分组条件的元素

val afterGroupBy = students.groupBy { it.age }
afterGroupBy.forEach { println("${it.key} ${it.value}") }

  groupBy里实际上可以放任何数据类型,它的目的就是将list分组转化成map

  例如下面我们以一个age to name的pair作为groupBy的条件

 

val students = mutableListOf<Student>(
    Student(1, "xiaoming", "guangzhou"),
    Student(2, "xiaohong2", "shenzhen"),
    Student(2, "xiaohong3", "chongqing"),
    Student(2, "xiaohong3", "chongqing"),
    Student(3, "xiaohei", "xian"),
    Student(3, "xiaohei2", "shenzhen"),
)
val afterGroupBy = students.groupBy { it.age to it.name }
afterGroupBy.forEach { println("${it.key} ${it.value}") }

 

  我们可以看到age为2,name为xiaohong3到student被groupBy起来了

 

map集合相关操作

mapValues

  对于一个map,我们可以将它的value进行一个映射

  例如这里有一个有一个Int到String的map,我们对这个map进行mapValues的操作

 

val map = mutableMapOf<Int,String>(1 to "a",2 to "b")
val map2 = map.mapValues { entry -> entry.value + "abc" }

 

  操作完map2里的value就是map里value拼接上abc的值

 

References

https://www.kotlincn.net/docs/reference/collections-overview.html

https://juejin.cn/post/6957922140767125517

https://www.kotlincn.net/docs/reference/collection-ordering.html

https://developer.android.com/codelabs/basic-android-kotlin-compose-collections?hl=zh-tw#0

 

posted @ 2023-03-09 19:46  艾尔夏尔-Layton  阅读(235)  评论(0编辑  收藏  举报