序列

引出序列的使用,首先当我们在使用集合的各种便携式API函数时,他会创建一个中间列表,最后返回。这在使用中并没有什么问题,但是如果采用了链式的多个函数操作,以及集合的基数很大时就会导致效率低下。
例如这个,他会在中途生成两个列表,如果基数很大将会变得非常低效。

1
people.map(Person: :name) .filter { it.startsWith ("A")}

而序列就是一种惰性集合,他一样可以使用集合所有的api方法,但是他不会在中间创造集合存储,而是类似java中的流。他是一个迭代器的形式,每个元素每个元素的遍历,然后最后在生成结果,如果没有最后的生成结果的步骤,他不会进行之前的操作。

Sequence接口

惰性集合的接口就是Sequence接口,而且他只提供了一个方法,也就是iterator。
因为Sequence是惰性的,所以他可以很高效的对集合元素执行链式操作,而且不会产生额外的中间集合。

序列操作


序列操作有两种,一种中间操作,他返回的任然是序列,一种是末端操作,他返回的结果,可以是任何所需要的对象。
中间操作始终是惰性的 ,也就是意味着,在链式操作中。如果是一般的集合,那么他们会先把所有元素都进行第一次中间操作,得到一个新集合,再进行第二次中间操作。而这就会带来内存的消耗。如果是惰性集合即序列时,他会按顺序把每个元素进行完所有的中间操作,然后返回。接下来再执行第二个元素。依次递进。

而且即便都是序列,不同的执行顺序也会有不同的性能开销。

生成Sequence

第一种生成Sequence的方式就是通过集合的asSequence()方法,第二种就是调用generateSequence(),给定序列的前一个元素,他就会根据函数推导出第二个函数。

1
2
3
4
5
6
7
8
9
10
11
12
fun main() {
val testSequence = generateSequence(1){it*2}
val result = testSequence.takeWhile { it<=1024 }
//延期操作
println(result.sum())

//迭代器的使用
var a = result.iterator()
for(i in a){
println(i)
}
}

结果如下:
需要注意的是testSequenceresult都是延期操作的序列,只有实际被调用,使用后才会进行求值。