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

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!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章