Kotlin常用Collection集合 *** 作整理

Kotlin常用Collection集合 *** 作整理,第1张

本篇记录了 Kotlin 常用集合的相关 *** 作,用以熟练使用 Kotlin 里的相关集合。集合接口与相关函数位于 kotlincollections 包中。

Kotlin 标准库提供了基本集合类型的实现: Set、List 以及 Map。 一对接口代表每种集合类型:

其中灰色是不可变集合,是可变集合。 Iterator 意为迭代器, Collection 是只读接口,而 MutableCollection 是一个具有写 *** 作的 Collection 接口:

List< T> 以指定的顺序存储元素,并提供使用索引访问元素的方法。从第一个元素索引0 到最后一个元素索引 (listsize - 1) 为止。 List 的默认实现是 ArrayList 。

执行结果会转化为 Map :

Set 内部是用 Map 实现的, Set 相关的实现详见: Java Collection系列之:HashSet、LinkedHashSet、TreeSet的使用及源码解析

Map<K, V> 不是 Collection 接口的继承者;但是它也是 Kotlin 的一种集合类型。 Map 存储 键-值 对(或 条目);键是唯一的,但是不同的键可以与相同的值配对。 Map 接口提供特定的函数进行通过键访问值、搜索键和值等 *** 作。 Map 相关的实现详见: Java Collection系列之HashMap、ConcurrentHashMap、LinkedHashMap的使用及源码分析

Iterable 处理包含多个步骤时,每个处理步骤完成并返回其结果——中间集合,然后在此集合上执行后续步骤。 Sequence 序列仅当请求整个处理链的结果时才进行实际计算: Sequence 对每个元素逐个执行所有处理步骤。

结论 :序列可避免生成中间步骤的结果,从而提高了整个集合处理链的性能。 但是,序列的延迟性质增加了一些开销,这些开销在处理较小的集合或进行更简单的计算时可能很重要。 因此,应该同时考虑使用 Sequence 与 Iterable ,并确定在哪种情况更适合。

执行结果:

执行结果:

上述序列中, Sequence 处理需要 18 个步骤, Iterable 需要 23 个步骤来执行列表 *** 作,上述示例参见 Sequence序列 *** 作 。

创建与现有集合具有相同元素的集合,可以使用复制 *** 作,例如 toList()、toMutableList()、toSet() 等等。标准库中的集合复制 *** 作创建了具有相同元素引用的 浅复制 集合。 因此, 对集合元素所做的更改会反映在其所有副本中,如果对源集合进行添加或删除元素,则不会影响副本 。

排序主要使用 Comparable 及 Comparator 。其中 Comparable 可以理解为是内部排序, Comparator 是外部排序。

集合排序示例:

这章理一下channel,先分享一句学习时候看到的话: Do not communicate by sharing memory; instead, share memory by communicating 。本来好像是用在 go 上的,但也有着异曲同工之妙啊

channel 顾名思义是管道,有入口与出口。因此最底层有 sendChannel&receiveChannel

Produce = Coroutine + Channel

produce 也是产生协程,跟普通的 launch 不同他会返回一个 receiveChannel ,后面会看到 receiveChannel 是一个迭代器,同时会 suspend 在 hasNext和next() 上,因此另一个协程就可以使用 forin 等待接受。

同时, produce 发射完成后是会自己关闭的,省的我们自己关闭信道:

通过 job 的 invokeOnCompletion 实现。

与 produce 相反返回 sendChannel

我们看这里用了 offer 而不是 send ,我们可以把 forin 先简单的写成以下形式:

假设队列里没有东西时, enqueue 一个 receiveHasNext 进行等待。过会解释一下 channel 的原理。现在只要知道,当有 sendersend 时,与 receive 关联的 cont 就会被调用 resume ,那么显而易见,当 action 正在处理时队列中没有 receiver ,而 offer 是不会 suspend 的,因此事件就被抛弃。

这里我们使用 CONFALTED ,即合并所有事件,因此接受者永远处理最近一个。原理如下:

当 offer 失败时需要 suspend 等待,(说明还没有接受者或者人家正忙着),插入 sendBuffered ,同时移除前面已有的 sendBuffered

这样永远是最近一个生效。

其实看 abstractChannel 会先看到一个 queue ,这时候显而易见会把它当做是像 linkedlist 那种塞数据的地方。但其实 queue 是用来放 receive/send node 。当队列为空时, send 时会先从队列取第一个 receiveNode ,取不到就 suspend ,把自己当成 sendNode 放入;不然就把数据直接交给 receiveNode 。

具体channel实现时,例如 ArrayChannel(buffer) ,会多加一个 buffer 队列,当队列为空时, send 时会先从队列取第一个 receiveNode ,取不到就放入 buffer 队列,如果 buffer 队列满了,把自己当成 sendNode 放入就 suspend ;同时把不然就把数据直接交给 receiveNode 。

参考

select 可以等任何一个回来,也可以等 await :

跟 linux 里的 select 其实类似,(能知道是哪个吗?):

能看到 onReceive 是实现 SelectCaluse1 ,同时在 selectBuilderImpl 环境下:

所以会往 queue 中 enqueue 两个 receive节点。 以

同时能看到如果任何一次 select 节点获取数据以后:

会调用 blockstartCoroutineUnintercepted :

之前讲过 startCoroutineUnintercepted 其实就是 functioninvoke() ,所以就调用 blockinvoke(select的completion是自己) ,获得值后通过 uContresume 即可。

这个和 defered 即 job(Support) 搞在一起:

可以看到当任务成功后, select 会被继续进行

首先解决一个问题,一个 sender 多个 receiver 是怎么处理的。

因为是1vs1消费。只有第一个会收到,因为它插在等待队列的第一个。用 broadcast 可以保证大家都收到。它维护一个 subscribe 的 user list ,所有消费者都能收到 channelsend 的 element

可以实现跟 RX 一样的 *** 作符,接受者收到后经过转换再进行发送返回最终新的 receiveChannel

channel 是 hot 的。

Provide abstraction for cold streams

这个todo,后续再说。

Even smarter async with coroutine actors

官方文档

Kotlin的集合类由两个接口派生:Collection和Map。Collection和Map是Java集合框架的根接口,这两个接口又包含一些子接口或实现类
Java中的集合都是可变集合,但Kotlin的集合被分为两大类:可变集合和不可变集合。

Kotlin也提供了Map集合。

Kotlin的Map派生了MutableMap接口,代表了一个可变的Map集合。

Kotlin并没有真正为JVM平台实现任何Set集合类通过别名借用了Java集合框架的类,不推荐使用构造器创建Set集合。推荐使用Kotlin提供的工具函数来创建Set集合

Kotlin除了Java原生Set的各种方法之外,Kotlin的Set还扩展了大量方法,在Set集合有很多方法与Array的方法功能相似,例如all、any、associate、drop、filter、find

Kotlin也支持使用for-in循环遍历Set,与遍历数组的基本方式相同

Set集合继承了Iteratable,因此可使用Iterable接口中定义的forEach()方法来遍历集合,该方法需要接受一个Lambda表达式作为参数

由于setOf()方法返回的Set集合是有序的,因此可以通过索引来遍历Set集合,Set集合也提供了indices方法返回集合的索引区间
···
//indices形式遍历
for (i in itSetindices) {
println(itSetelementAt(i))
}
···

mutableSetOf()、hashSetOf()、linkedSetOf()、sortedSetOf()函数返回的集合都是可变的,依次是Set、HashSet、LinkedHashSet、TreeSet

List集合的特点:

Kotlin并未真正的实现List集合,只是通过别名借用了Java体系中的ArrayList集合。

mutableListOf()、arraysListOf() 函数返回的List集合都是可变的

与Java相同,Kotlin的Map集合同样用于保存key-value对
与Java不同,Kotlin的Map集合也分为可变的和不可变的

Kotlin并没有真正的为JVM平台实现任何Map集合类。

Map集合由多个key-value组成,因此遍历Map集合时可通过对key-value对进行遍历,也可先遍历key,再通过key获取value遍历


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/dianzi/13490334.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-08-17
下一篇 2023-08-17

发表评论

登录后才能评论

评论列表(0条)

保存