Kotlin sequence序列生成以及generateSequence()、yield()函數的使用

sequence稱之爲序列,也是一種容器類型--(Sequence<T>),序列提供了和迭代器(Iterable)相同的函數,只不過序列的實現方式跟普通的集合處理方式不同而已。函數

首先序列式惰性的,惰性的含義就是咱們對序列進行各類一些列的變換的操做的時候,會對序列中的元素依次進行變換而且保存到Sequence對象裏面,當咱們求情整個處理鏈的結果的時候纔會進行最終的計算而且返回對應的結果好比Int、Boolean、List<T>。避免產生了中間步驟的結果,從而提升了整個集合處理鏈的性能。普通的集合在進行變換操做的時候是先遍歷集合中的元素依次處理而且返回一個新的集合而後在此基礎之上再進行其他的操做,最後返回結果,可見其中會產生不少的性能消耗。但是序列的延遲性質也增長了一些消耗,這些開銷在處理在處理較小的集合的時候會顯得很重要了。所以怎麼選擇哪一種狀況更合適顯得很重要。性能

今天着重記錄了一下序列的基本使用以及sequence()函數的使用。spa

咱們若是想直接建立一個序列能夠這樣直接建立:翻譯

val sequence1 = sequenceOf("a", "b", "c")

使用的時候咱們能夠直接toList進行list的遍歷等操做。對象

還能夠在List的基礎之上進行轉換序列操做:blog

val list = listOf("d", "e", "f")
val sequence2 = list.asSequence()
println(sequence2.toList())

就能夠很輕鬆的進行序列的轉換了。it

使用起來比較簡單,重要的就是要了解序列它的實現原理,它跟集合的不一樣的地方。class

還有一種方式咱們經過計算函數的方式來計算序列中元素的構建過程。這時候咱們要用到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) // 一、三、5
    yieldAll(generateSequence(8) { it * 3 }) //八、2四、72
}

yield函數是對序列生產一個元素,放入序列之中,而且暫停sequence()函數執行,直到下一個請求函數元素到來。

首先咱們先往序列裏面放入0這個元素,而後又放入一個list,規則step函數 一、三、5集合,最後經過generateSequence()經過函數生成元素而且最後咱們take(7),取前七個爲止輸出以下:

[0, 1, 3, 5, 8, 24, 72]

ok!

相關文章
相關標籤/搜索