Kotlin集合简介

本文介绍了Kotlin中集合的声明,包括可变与不可变集合,如List、MutableList、Set和MutableSet等。接着详细讨论了常用集合API,如all、any、count、filter、map等,并通过案例分析解释了它们的工作原理。最后,文章深入探讨了延迟集合操作Sequences,阐述了其优化性能的原理,以及何时应该使用Sequence来处理大量数据。
摘要由CSDN通过智能技术生成

本文整理自:https://chiclaim.blog.csdn.net/article/details/85575213

Kotlin 中的集合底层也是使用 Java 集合框架那一套。在上层又封装了一层 可变集合 和 不可变集合 接口。

下面是 Kotlin 封装的可变集合和不可变集合接口:

接口                      是否可变              所在文件
List                       不可变                   Collections.kt
MutableList           可变                      Collections.kt
Set                       不可变                   Collections.kt
MutableSet           可变                     Collections.kt
Map                     不可变                   Collections.kt
MutableMap          可变                     Collections.kt
 

一、声明可变集合

二、声明不可变集合

通过 Kotlin 提供的 API 可以方便的创建各种集合,但是同时需要搞清楚该 API 创建的集合底层到底是对应 Java 的哪个集合。

三、Kotlin 集合常用的 API

1) all、any、count、find、firstOrNull、groupBy 函数

2) filter、map、flatMap、flatten 函数

案例分析:list.map(Person::age).filter { it > 18 }

虽然 list.map(Person::age).filter { it > 18 } 代码非常简洁,我们要知道底层做了些什么?反编译代码如下:

发现调用 map 和 filter 分别创建了一个集合,也就是整个操作创建了两个 2 集合。

四、延迟集合操作之 Sequences

根据上面的分析,list.map(Person::age).filter { it > 18 } 会创建两个集合,本来常规操作一个集合就够了,Sequence就是就是为了避免创建多余的集合的问题。

val list = listOf<Person>(Person("chiclaim", 18), Person("yuzhiqiang", 15),
        Person("johnny", 27), Person("jackson", 190),
        Person("pony", 85))
        
//把 filter 函数放置前面,可以有效减少 map 函数的调用次数
list.asSequence().filter { person ->
    println("filter---> ${person.name} : ${person.age}")
    person.age > 20
}.map { person ->
    println("map----> ${person.name} : ${person.age}")
    person.age
}.forEach {
    println("---------符合条件的年龄 $it")
}

为了提高效率,我们把 filter 调用放到了前面,并且加了一些测试输出:

filter---> chiclaim : 18
filter---> yuzhiqiang : 15
filter---> johnny : 27
map----> johnny : 27
---------符合条件的年龄 27
filter---> jackson : 190
map----> jackson : 190
---------符合条件的年龄 190
filter---> pony : 85
map----> pony : 85
---------符合条件的年龄 85

从这个输出日志我们可以总结出 Sequence 的原理:

集合的元素有序的经过 filte r操作,如果满足 filter 条件,再经过 map 操作。

而不会新建一个集合存放符合 filter 条件的元素,然后在创建一个集合存放 map 的元素

Sequence 的原理图如下所示:

需要注意的是,如果集合的数量不是特别大,并不建议使用 Sequence 的方式来进行操作。我们来看下 Sequence<T>.map 函数

public fun <T, R> Sequence<T>.map(transform: (T) -> R): Sequence<R> {
    return TransformingSequence(this, transform)
}

它是一个高阶函数,但是它并没有内联,为啥没有内联?因为它把 transform 传递给了 TransformingSequence,然后TransformingSequence通过属性将其保存起来了,并没有直接使用 transform,所以不能内联。

根据上面我们对高阶函数的分析,如果一个高阶函数没有内联,每调用一次该函数都会创建内部类。

除此之外还有一点也需要注意,下面一段代码实际上不会执行:
 

list.asSequence().filter { person ->
    person.age > 20
}.map { person ->
    person.age
}

只有用到了该 Sequence 里的元素才会触发上面的操作,比如后面调用了 forEach、toList 等操作。

对 Sequence 做一个小结

如果集合的数据量很大啊,可以使用集合操作的延迟 Sequence
Sequence 的 filter、map 等扩展还是是一个非 inline 的高阶函数
集合的 Sequence 只有调用 forEach、toList 等操作,才会触发对集合的操作。有点类似 RxJava。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值