DEVLOG 11.4 Kotlin Collections vs Java Collections

Kotlin中的集合的设计理念
range progression
Kotlin中的集合和Java中的集合的互操作
设计理念和基本操作
Kotlin中的集合分成Mutable和Immutable两种类型,可变和不可变这里应该理解为【是否只读】。Kotlin Collection类中只定义了如下的方法:
Collection不是可变的,对应的可变集合应该是MutableCollection,而MutableCollection相对于Collection多了一些增加、删除方法。
我们常用的快捷创建集合的函数listOf创建的是一个List:
在Kotlin中创建Map也非常方便:
等差数列 Arithmetic progression
定义在Progressions.kt 中的只有三种等差数列,IntProgression,CharProgression和LongProgression,当然其他的类型也不太好进行等差。举个例子,IntProgression。等差数列需要的三个基本的量都定义在构造器中:
我们最常用的其实是Progression的其中一种子类型,IntRange:
reversed filter这些扩展函数返回的都是当前range的副本。
和Java中的集合的互操作
虽然Kotlin中的集合定义看起来像另外一套系统,并且定义在java.utils包中的ArrayList这些类明显和后来定义在Kotlin Collection中的List以及MutableList没有明显的继承关系,但是在一些情况下,好像可以对于List和MutableList进行【向下转型】成ArrayList,比如:
看起来是一个【向下转型】,但是实际上是怎么做的呢?具体得看看Iterable的扩展函数toList:
也就是说,range(本身是一个Iterable),它在toList的时候,底层就是会新建一个ArrayList并返回,这伪装成了一个向下转型的操作。
WAIT WAIT WAIT
我真的麻了,Java中先定义的ArrayList怎么会变成后面Kotlin定义的MutableList的子类型?
在Kotlin的github仓库,我们可以看到ArrayList在Kotlin stdlib中的定义:
expect关键字表示Kotlin会从当前的平台找到对应的ArrayList的支持,在JVM上,它的支持就是:

所以Kotlin中的ArrayList是套皮了java.util中的ArrayList,但是在形式上还真的是一个MutableList。
因此Kotlin和Java的Collection确实是两个分开的系统,我们不能随便拿一个toList就认为可以转化成Java的集合中的类型。
一个失败的例子
Iterable.toList会返回一个ArrayList,那我这样写应该没问题了吧:

但是会出错:

具体看看代码:
最后返回的是Java的Arrays里面一个叫做ArrayList的子类,并不是我们的ArrayList。
所以分析一下这里的性能消耗,range.toList创建了一个ArraylistKt,然后sortedByDescending又转化成了Array进行比较,即使这行代码可以运行,性能损失也是比较大的。
为了语法上通过,我们应该这样写:
两者的性能没有提升,Kotlin这种操作用起来爽是很爽,但是性能上不一定占优势