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

2023年 7月 12日 40.6k 0

序列(Sequence) VS 集合(Iterable)

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

举个例子:给定一个字符串,过滤长于三个字符的单词,并打印前四个单词的长度

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。

流程图:引用自官网 Kotlin笔记:Sequence的使用及与Iterable的区别 Sequence写法:

 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) 可以返回的最大大小。

流程图:引用自 Kotlin笔记:Sequence的使用及与Iterable的区别

在此示例中,序列处理需要 18 个步骤,而不是 23 个步骤来执行列表操作

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

静态创建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语法糖)

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

    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操作,将被忽视

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

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论