Kotlin集合类

  • Kotlin从入门进阶到实战

  • Kotlin是在java类库基础上进行了改造和扩展,引入了不可变集合类,同时扩展了大量方便实用的功能,这些功能api都在kotlin.collections包下。

  • 在kotlin集合类中不仅能支持普通对象,而且能够持有函数类型的变量。

val funList: List<(Int) -> Boolean> = listOf({ it -> it % 2 == 0 }, { it -> it % 2 == 1 })

    fun test() {
        val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
        val result = list.filter(funList[0])
        val result1 = list.filter(funList[1])
        println(result)
        println(result1)
    }

这就是面向对象式和函数式编程混合开发的样子

Kotlin集合类概述
  • Kotlin集合类可以分为:可变集合类(Mutable)和不可变集合类(Immutable)。
  • 常用的集合类主要有三种:List(列表)、Set(集)和Map(映射)
  • List容器中的元素以线性方式存储,集合中可以存放重复对象。列表中的数据是有序排列
  • Set集容器的元素无序、不重复。
  • Map映射的持有的是 键值对 对象每一个对象都包含一堆 K-V对象。Map存储的容器中每一个对象都有一个Key对象,Key决定对象在容器中的位置。关键字Key是唯一的。关键字本身并不能决定对象的存储位置,它通过散列产生一个 散列码 的整数值,这个散列码对应值Value的存储位置。
  • 如果从数据结构本身来看List中的下标就是Key,只不过key是有序的Int类型,所以说List也可以成为特殊的Map数据结构。而Set也是Key为Int值,但是Value不能重复。.
Kotlin集合类继承层次

在这里插入图片描述

  • Iterable 父类任何类继承这个接口就表示可以遍历序列元素
  • MutableIteIterable 在迭代器期间支持删除元素的迭代
  • Collocation List和Set的父类接口,只可读不可变
  • MutableCollection 支持添加和删除元素的Collection。它提供了写入的函数,如add、remove或clear等
  • List 最常用的集合,继承Collection接口,元素有序,只读不可变
  • MutableList 继承List,之处添加和删除元素,除了拥有List中读取的函数,还有add、remove或clear等写入数据的函数
  • Set 元素无重复、无序。继承Collection接口。只读不可变
  • MutableSet 继承Set,支持添加和删除元素Set
  • Map 存储K-V对的集合,在Map映射表中Key是唯一的。
  • MutableMap 支持添加和删除元素的Map
不可变集合类
  • List列表分为只读不可变的List和可变MutableList。List列表的类型层次结构如下
    在这里插入图片描述
  • Set集合也分为不可变Set和可变MutableSet。Set集合类的类型层次如下
    在这里插入图片描述
  • Kotlin中Map和Set一样分为 只读Map和可变MutableMap。Map没有继承Collection接口。
    在这里插入图片描述
创建集合类
  • Kotlin中分别用 listOf()setOf()mapOf() 创建不可变的容器,使用mutableListOf()mutableSetOf()mutableMapOf() 创建可变的Mutable容器
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 代码示例如下

val list = listOf(1, 2, 3, 4, 5)//创建不可变List
val mutableList = mutableListOf(1, 2, 3, 4, 5)//创建可变mutableList

val set = setOf(1,2,3,4,5)//创建不可变Set
val mutableSet = mutableSetOf(1,2,3,4,5)//创建可变mutableSet

val map = mapOf(1 to "A" , 2 to "B" ,3 to "C")//创建不可变Map
val mutableMap = mutableMapOf(1 to "A" , 2 to "B" ,3 to "C")//创建可变mutableMap
  • 如果创建没有元素的空List使用ListOf()即可。不过需要显式指定变量的类型。否则会报错
Type inference failed: Not enough information to infer parameter T in inline fun <T> listOf( ): List<T> Please specify it explicitly.
val list = listOf<Int>()
val set = setOf<String>()
val map = mapOf<Int,String>()
遍历集合中的元素
  • List、Set集合继承了Iterable接口,里面扩展了forEach函数来迭代遍历元素。同样Map接口也扩展了forEach函数迭代遍历元素。
val list = listOf<Int>(1, 2, 3, 4, 5, 6)
list.forEach { println(it) }

val set = setOf<String>("A", "B", "C")
set.forEach { println(it) }

val map = mapOf<Int, String>(1 to "o", 2 to "p", 3 to "q")
map.forEach { println("key = ${it.key} value = ${it.value}") }

在Iterable和Map中,forEach函数都是一个内联inline函数。另外如果我们想在迭代器遍历的时候获取index下标,在List和Set中可以使用下面的forEachIndexed函数

val list = listOf<Int>(1, 2, 3, 4, 5, 6)
//第一个参数是index 第二个参数 i 是value
list.forEachIndexed { index, i -> println("index = ${index} value = ${i}") }

val set = setOf<String>("A", "B", "C")
set.forEachIndexed { index, s -> println("index = ${index} value = ${s}") }

Map的元素是Entry类型,有entries属性持有

 public val entries: Set<Map.Entry<K, V>>

这个Entry类型定义如下

 public interface Entry<out K, out V> {
        /**
         * Returns the key of this key/value pair.
         */
        public val key: K

        /**
         * Returns the value of this key/value pair.
         */
        public val value: V
    }

可以通过Entry属性获取Map所有键值对的Set

 val map = mapOf(1 to "o", 2 to "p", 3 to "q")
map.entries.forEach { println("key = ${it.key} , value = ${it.value}") }

key = 1 , value = o
key = 2 , value = p
key = 3 , value = q

映射函数
  • 使用map函数,可以把集合中的元素依次使用给定的转换函数进行映射操作,元素映射之后的新值会存入一个新的集合中,并且返回这个新集合。
  • 在List、Set继承的Iterable接口和Map接口中,都提供了这个map函数。使用map的代码示例如下:
val list = listOf(1, 2, 3, 4, 5, 6)
val mapForList = list.map { it * it }// map函数对每个元素进行乘方操作
println(mapForList)

//输出结果如下
[1, 4, 9, 16, 25, 36]
val set = setOf("A", "B", "C")
val mapForSet = set.map { it + "helloMap" }//map函数对每个元素进行字符串拼接
println(mapForSet)

//输出结果如下
[AhelloMap, BhelloMap, ChelloMap]
val map = mapOf(1 to "o", 2 to "p", 3 to "q")
val mapForMap = map.map { it.value + "Map" }
println(mapForMap)
//输出结果如下
[oMap, pMap, qMap]

map函数如下:

public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}

这里的R类型是映射之后的数据类型,我们也可以传入一个List

val list = listOf(1, 2, 3, 4, 5, 6)
val mapFList = list.map { it -> listOf(it + 100, it + 1000, it + 10000) }
println(mapFList)

输出结果如下,每个元素映射为一个List,这个List中有三个元素 分别为 it + 100 it+1000 it+10000 ,这个时候返回值会是List套一个List

[[101, 1001, 10001], [102, 1002, 10002], [103, 1003, 10003], [104, 1004, 10004], [105, 1005, 10005], [106, 1006, 10006]]

Kotlin中还提供了一个flattern函数,效果是使结构变为一层还是上边的代码

val list = listOf(1, 2, 3, 4, 5, 6)
val mapFList = list.map { it -> listOf(it + 100, it + 1000, it + 10000) }.flatten()
println(mapFList)

输出如下

[101, 1001, 10001, 102, 1002, 10002, 103, 1003, 10003, 104, 1004, 10004, 105, 1005, 10005, 106, 1006, 10006]

flatMap函数是map和flat两个函数的复合逻辑,代码如下

val list = listOf(1, 2, 3, 4, 5, 6)
val mapFList =   list.flatMap { it -> listOf(it + 1, it + 2) }
println(mapFList)

输出结果如下

[2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8]
过滤函数
  • 使用filter()函数,下面是代码示例
data class Student(var name: String, var age: Int, var score: Int) {
        override fun toString(): String {
            return "$name ${age}岁 ${score}分"
        }
    }

    @JvmStatic
    fun main(args: Array<String>) {
        val list = listOf(Student("张三", 18, 80)
                , Student("小明", 16, 70)
                , Student("小李", 16, 50)
                , Student("小王", 20, 100)
                , Student("小陆", 18, 59))
        val filter = list.filter { it.score < 60 }
        println(filter)
    }

如果想找到成绩不及格的学生。使用 list.filter { it.score < 60 }

[小李 16岁 50分, 小陆 18岁 59分]

如果查看年龄>= 18岁的

   val filter = list.filter { it.age >= 18 }
   //输出结果如下
   //[张三 18岁 80分, 小王 20岁 100分, 小陆 18岁 59分]
  • 如果想通过下标来过滤,可以用filterIndexed
val filter = list.filterIndexed { index, student -> index % 2 == 0 && student.score > 55}
//输出  [张三 18岁 80分, 小陆 18岁 59分]
val filter = list.filterIndexed { index, student -> index % 2 == 0 && index > 3 }
//输出 [小陆 18岁 59分]

filterIndexed()函数如下

public inline fun <T> Iterable<T>.filterIndexed(predicate: (index: Int, T) -> Boolean): List<T> {
    return filterIndexedTo(ArrayList<T>(), predicate)
}
排序函数
  • Kotlin集合类的提供了倒叙排序的集合元素的函数reversed(),示例如下
@JvmStatic
    fun main(args: Array<String>) {
        val list = listOf(1, 2, 3)
        val set = setOf(4, 5, 6)
        println(list.reversed())
        println(set.reversed())
    }

打印输出如下

[3, 2, 1]
[6, 5, 4]

这个Iterable的扩展函数reversed()是直接调用的java.util.Collections.reverse()

public fun <T> Iterable<T>.reversed(): List<T> {
    if (this is Collection && size <= 1) return toList()
    val list = toMutableList()
    list.reverse()//调用java中List类型的reverse()方法
    return list
}
  • 升序排列是用sorted()
@JvmStatic
    fun main(args: Array<String>) {
        val list = mutableListOf(3, 2, 1)
        val set = setOf(6, 5, 4)
        println(list.sorted())
        println(set.sorted())
    }

输出如下

[1, 2, 3]
[4, 5, 6]

sorted()也是直接调用了java api来实现的

public fun <T : Comparable<T>> Iterable<T>.sorted(): List<T> {
    if (this is Collection) {
        if (size <= 1) return this.toList()
        @Suppress("UNCHECKED_CAST")
        return (toTypedArray<Comparable<T>>() as Array<T>).apply { sort() }.asList()
    }
    return toMutableList().apply { sort() }
}

最终调用java.util.Arrays.sort()

public actual fun <T : Comparable<T>> MutableList<T>.sort(): Unit {
    if (size > 1) java.util.Collections.sort(this)
}
元素去重
  • distinct()
@JvmStatic
    fun main(args: Array<String>) {
        val list = listOf(1, 2, 3, 4, 2, 5, 6, 4, 3, 5, 3, 1, 9)
        println(list.distinct())
    }

打印输出

[1, 2, 3, 4, 5, 6, 9]
   data class Student(var name: String, var age: Int, var score: Int) {
        override fun toString(): String {
            return "$name ${age}岁 ${score}分"
        }
    }

    @JvmStatic
    fun main(args: Array<String>) {
        val list = listOf(Student("张", 10, 100)
                , Student("张", 10, 100)
                , Student("李", 20, 90))
        println(list.distinct())
    }

输出结果如下

[张 10岁 100分, 李 20岁 90分]
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值