sequence称之为序列,也是一种容器类型--(Sequence<T>),序列提供了和迭代器(Iterable)相同的函数,只不过序列的实现方式跟普通的集合处理方式不一样而已。
首先序列式惰性的,惰性的含义就是我们对序列进行各种一些列的变换的操作的时候,会对序列中的元素依次进行变换并且保存到Sequence对象里面,当我们求情整个处理链的结果的时候才会进行最终的计算并且返回对应的结果比如Int、Boolean、List<T>。避免产生了中间步骤的结果,从而提高了整个集合处理链的性能。普通的集合在进行变换操作的时候是先遍历集合中的元素依次处理并且返回一个新的集合然后在此基础之上再进行其余的操作,最后返回结果,可见其中会产生很多的性能消耗。可是序列的延迟性质也增加了一些消耗,这些开销在处理在处理较小的集合的时候会显得很重要了。因此怎么选择哪种情况更合适显得很重要。
今天着重记录了一下序列的基本使用以及sequence()函数的使用。
我们如果想直接创建一个序列可以这样直接创建:
val sequence1 = sequenceOf("a", "b", "c")
使用的时候我们可以直接toList进行list的遍历等操作。
还可以在List的基础之上进行转换序列操作:
val list = listOf("d", "e", "f") val sequence2 = list.asSequence() println(sequence2.toList())
就可以很轻松的进行序列的转换了。
使用起来比较简单,重要的就是要了解序列它的实现原理,它跟集合的不同的地方。
还有一种方式我们通过计算函数的方式来计算序列中元素的构建过程。这时候我们要用到generateSequence()函数了,它是一个没有边界的序列,大小可以无限的生长,知道提供的元素的函数返回null为止,序列也就停止生成了。
val generateSequence = generateSequence(2) { it * 3 }.take(10) println(generateSequence.toList())
其中的2的含义是说我们的序列从2开始然后根据传入的函数参数规则进行生成序列元素,我们的这里的规则就是上一个元素*3就是下一个元素的值。
打印出来如下:
[2, 6, 18, 54, 162, 486, 1458, 4374, 13122, 39366]
这个是最基本的使用方式,我们看到take()函数,它需要我们传递一个Int的数值,告诉序列我取到第十个的时候就停止了,序列也就不会再产生元素了。
点进去发现其实他返回的还是序列对象:
说明这个函数还不是最终的计算方法,返回的还是序列sequence对象,真正最后通过toList之后返回的就是一个集合了:
最后的返回就是一个集合了,这才是序列最后计算的时刻,同样的toList函数,这里就是序列的扩展函数了,使用方法就不一样了。
还有一种实现方式可以终止函数的生成,不用take()函数来终止了,我们可以通过自己定义的元素生成函数来实现:
val generateSequence1 = generateSequence(2){ if((it +3) < 20) it + 3 else null } println(generateSequence1.toList())
打印如下:
[2, 5, 8, 11, 14, 17]
当生成的元素小于20的时候函数就会直接返回null,那么序列就停止生成了。
最后呢,我记录了一下yield()函数,翻译过来是生产、产生的意思,那就顾名思义了。
使用方法看看这个例子:
val sequence = sequence { val start = 0 yield(start) // 依次放入序列之中 0 yieldAll(1..5 step 2) // 1、3、5 yieldAll(generateSequence(8) { it * 3 }) //8、24、72 }
yield函数是对序列生产一个元素,放入序列之中,并且暂停sequence()函数执行,直到下一个请求函数元素到来。
首先我们先往序列里面放入0这个元素,然后又放入一个list,规则step函数 1、3、5集合,最后通过generateSequence()通过函数生成元素并且最后我们take(7),取前七个为止输出如下:
[0, 1, 3, 5, 8, 24, 72]
ok!