Kotlin 随笔 collection & sequence

Kotlin 随笔 collection & sequence

在日常的工作中,我们会经常的使用到集合,Kotlin 标准库中提供了非常出色的关于集合的工具函数。Kotlin 提供了基于不同执行方式的两种集合类型,立即执行的Collection 类型和延迟执行的 Sequence 类型。
Kotlin 随笔 collection & sequence
这里将介绍两者的不同,以及分别该在那种情况下使用,以及他们的两者的性能表现。

立即执行延迟执行这两种执行方式的区别,在于集合操作的每次转换在何时得以真正的执行。Kotlin 随笔 collection & sequence
假如有一个列表,存储了许多不同形状的对象。我们希望将列表中形状的颜色变成黄色,然后获取获取列表中的第一个正方形。
让我们先来使用 Collection 进行操作。
Kotlin 随笔 collection & sequence

首先我们使用map函数。
Kotlin 随笔 collection & sequence
一个新的ArrayList 会被创建。我们遍历了初始Collection 中的所有项目,复制原始的对象然后改变它的颜色,在将其添加到新的列表中去。
接下来first被调用,遍历每一个项目直到找到第一个正方形。
Kotlin 随笔 collection & sequence

  • 使用Collection 时操作是立即处理的,每次操作都会发生在调用时就被执行,直到 将整个Collection执行完。
  • 执行结果会保存到一个新的Collection中。
  • 作用于Collection 上的转换操作都是内联函数。

查看map的实现方式
Kotlin 随笔 collection & sequence
这里就是一个负责创建新的ArrayList 的内联函数。

接下来再来看看使用Sequence 时又会发生什么。
Kotlin 随笔 collection & sequence
首先,要调用的方法是asSequence。
Kotlin 随笔 collection & sequence
然后会基于原始集合的迭代器创建一个Sequence。Kotlin 随笔 collection & sequence

接着map方法被调用,这里的map是一个中间操作。现在,转换操作的信息会被存储到一个列表中,该列表只会存储需要执行的操作,并不会执行这些操作。
Kotlin 随笔 collection & sequence
最后调用first方法。这是一个末端操作,所有会将所有的中间操作作用到集合中的每个元素。
Kotlin 随笔 collection & sequence
我们遍历初始集合,对每个元素执行map操作,然后再继续执行first操作。
当遍历到第二个元素时,发现它符合我们的要求,所以就无需再对剩下的元素进行map操作了。

使用Sequence 时不会去创建中间集合。
由于元素数据会被逐个执行,map操作执行作用到部分输入上。
Kotlin 随笔 collection & sequence
Map不在是内联函数,因为转换函数而被传至一个转换序列对象中进行存储。进一步看一下TransformingSequence这样的类型是如何实现的,我们会发现在迭代器上调用next时,转换存储操作也一并被应用了。

无论你使用的是Collection 还是 Sequence,Kotlin 标准库都提供了一系列操作,比如find、filter、groupBy等等。使用他们之前,你得确保真正了解他们是如何进行工作的。

接下来,我们来讨论一下他们的性能问题:
无论,是使用Collection还是使用Sequence,转换的顺序都很重要。

在上面的例子当中,事实上first 不需要在map之后进行操作,因为他们不需要map操作的结果就能执行。如果我们颠倒业务顺序,先把first作用到Collection上,再对结果执行转换,那么我们只会创建一个新的对象,一个黄色的正方形,仍然可以得到正确的结果。
当使用Sequence时,要避免创建两个新的对象。当使用Collection时,要避免创建整个列表。因为末端操作可以提前对任务进行处理,而中间操作会延迟进行处理,所以,在某些情况下Sequence相较于Collection来说可以避免一些不必要的操作。所以要确保你要进行的转换顺序,以及他们之间的依赖关系