Kotlin笔记:Sequence的使用及与Iterable的区别

2021-03-0311:33:22编程语言入门到精通Comments2,034 views字数 2227阅读模式

序列(Sequence) VS 集合(Iterable)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

Kotlin笔记:Sequence的使用及与Iterable的区别
Kotlin笔记:Sequence的使用及与Iterable的区别文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

举个例子:给定一个字符串,过滤长于三个字符的单词,并打印前四个单词的长度文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

Iterable写法:

fun main() {    
    val words = "The quick brown fox jumps over the lazy dog".split(" ")
    val lengthsList =  { println("filter: $it");  > 3 }
        .map { println("length: ${}");  }
        .take(4)

    println("Lengths of first 4 words longer than 3 chars:")
    println(lengthsList)
}
 >>>filter: The
filter: quick
filter: brown
filter: fox
filter: jumps
filter: over
filter: the
filter: lazy
filter: dog
length: 5
length: 5
length: 5
length: 4
length: 4
Lengths of first 4 words longer than 3 chars:
[5, 5, 5, 4]

运行此代码时,会看到 filter() 与 map() 函数的执行顺序与代码中出现的顺序相同。
filter作用于所有元素,length作用于过滤之后剩余的元素,最后是两个println。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

流程图:引用自官网
Kotlin笔记:Sequence的使用及与Iterable的区别
Sequence写法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

 fun main() {
        val words = "The quick brown fox jumps over the lazy dog".split(" ")
        // 将列表转换为序列
        val wordsSequence = ()

        val lengthsSequence =  { println("filter: $it");  > 3 }
            .map { println("length: ${}");  }
            .take(4)

        println("Lengths of first 4 words longer than 3 chars")
        // 末端操作:以列表形式获取结果。
        println(())
 }
    
>>> Lengths of first 4 words longer than 3 chars
filter: The
filter: quick
length: 5
filter: brown
length: 5
filter: fox
filter: jumps
length: 5
filter: over
length: 4
[5, 5, 5, 4]

此代码的输出表明,仅在构建结果列表时才调用 filter() 与 map() 函数。
因此,首先看到文本 “Lengths of…” 的行,然后开始进行序列处理。
注意:对于过滤后剩余的元素,映射在过滤下一个元素之前执行。当结果大小达到 4 时,处理将停止,因为它是 take(4) 可以返回的最大大小。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

流程图:引用自
Kotlin笔记:Sequence的使用及与Iterable的区别文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

在此示例中,序列处理需要 18 个步骤,而不是 23 个步骤来执行列表操作文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

总结:
①Sequence会对每个元素逐个执行所有操作步骤,因此能够有效减少中间步骤的执行,从而提高整个收集链的性能。
②Sequence具备延迟性质,只有在请求整个处理链的结果时才进行实际计算,所以也具备一定的开销。这些开销在处理较小的集合或进行简单的计算时也许很重要
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

静态创建Sequence

// method one : 调用 sequenceOf() 方法,传入相应参数
val numSequence = sequenceOf("one","two","three")

// method two : 调用 asSequence() 
val numbers = listOf("one", "two", "three", "four")
val numbersSequence = ()

// 使用 generateSequence() 创建
val numberSequence = generateSequence(1) { if (it + 2 < 10) it + 2 else null }

动态创建Sequence

调用sequence()函数,该函数接收一个lambda表达式,其中包含yield()和yieldAll()函数的调用。下面例子的写法解释一下:lambda表达式作为函数调用的最后一个实参时,可以放在括号外边。当lambda是函数唯一的实参时,还可以去掉调用代码中的空括号对(kotlin语法糖)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

yield:礼让,即当前元素返回给sequence之后就暂停该sequence() 的执行,直到使用者请求下一个元素。
yield() 使用单个元素作为参数;
yieldAll() 中可以采用 Iterable 对象、Iterable 或其他 Sequence。yieldAll() 的 Sequence 参数可以是无限的。
当然,这样的调用必须是最后一个:否则在这之后的所有调用都不会执行。//①文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

    val oddNumbers = sequence {
        yield(1)
        yieldAll(listOf(3, 5))
        yieldAll(generateSequence(7) { it + 2 })
    }
    println((12).toList())
>>> [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23]

解释一下注释①,意思就是如果无限产生数据的yieldAll()之后还有yield操作,将被忽视文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html

val oddNumbers = sequence {
    yield(1)
    yieldAll(generateSequence(7) { it + 2 })
    yieldAll(listOf(3, 5))
    
}
println((5).toList())
>>> [1, 7, 9, 11, 13]
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/21002.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/21002.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定