以前探究集合的函数式Api时发现,这些函数都会遍历集合而且提前建立新集合,每一步的中间结果会被存储在新集合中。当数据量很大时,调用十分的低效。android
fun main(args: Array<String>) {
val list = (1..10).toList()
list.filter {
it % 2 == 0
}.map {
it * it
}.forEach {
println(it)
}
}
复制代码
序列对每一个元素逐个执行全部处理步骤,能够避免构建中间变量,提升整个集合处理链的性能。序列也称为惰性集合,序列与Java8中的Stream很像,序列是Kotlin对流这种概念提供的实现。设计模式
Kotlin惰性集合操做的入口是 Sequence
接口。该接口只有 iterator
方法,用来从序列中获取值。bash
public interface Sequence<out T> {
public operator fun iterator(): Iterator<T>
}
复制代码
建立序列有四种方式:ide
sequenceOf()
,将元素做为其参数。(相似建立集合的那一堆顶层函数,如listOf)val numbers= sequenceOf(1,2,3,4,5,6,7,8,9,10)
复制代码
asSequence()
将集合转换为序列。(经常使用)val numbers = (1..10).toList().asSequence()
复制代码
generateSequence()
。给定一个初识的元素,并提供函数计算下一个元素。该函数会一直生成序列的元素,直到函数实参返回null为止。若是函数实参不返回null,则该序列将是一个无限序列:val numbers = generateSequence(6){
it + 2
}
复制代码
使用generateSequence()
提供有限序列:函数
val numbers = generateSequence(6){
if (it < 10)
it + 2
else
null
}
复制代码
sequence()
函数.该函数接收一个函数类型为 SequenceScope<T>.() -> Unit
的实参。能够在传递给sequence()
函数的lambda表达式中使用SequenceScope
对象的 yield() 和 yieldAll() 添加序列元素。yield()用于添加单个序列元素; yieldAll()用于将列表或序列中的元素转化为新序列的元素。val numbers = sequence{
yield(1)
yieldAll(listOf(2,3))
yieldAll(setOf(4,5))
yieldAll(generateSequence(6){
if (it < 10)
it + 1
else
null
})
}
复制代码
序列同样能够像集合同样调用函数式Api,但序列的操做分为两大类:中间操做和终端操做。post
中间操做的定义:中间操做始终是惰性的,中间操做返回的是另外一个序列。性能
能够经过函数的返回信息,判断是否为中间操做:ui
//filter函数,返回Sequence<T>,中间操做。
//注意这是一个带Sequence<T>接收者的函数类型参数!!
public fun <T> Sequence<T>.filter(predicate: (T) -> Boolean): Sequence<T> {
return FilteringSequence(this, true, predicate)
}
//map函数,返回Sequence<T>,中间操做
//注意这是一个带Sequence<T>接收者的函数类型参数!!
public fun <T, R> Sequence<T>.map(transform: (T) -> R): Sequence<R> {
return TransformingSequence(this, transform)
}
复制代码
惰性怎么理解呢?执行如下例子:this
val list = (1..10).toList()
list.asSequence()
.filter {
println("filter $it")
it % 2 == 0
}.map {
println("map $it")
it * it
}
复制代码
末端操做定义:触发执行全部的延期计算(指中间操做),并返回一个结果,结果多是集合、数字等。spa
//forEach函数,返回值不是序列,末端操做
//注意这是一个带Sequence<T>接收者的函数类型参数!
public inline fun <T> Sequence<T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
//count函数,返回值不是序列,末端操做
//注意这是一个带Sequence<T>接收者的函数类型参数!
public inline fun <T> Sequence<T>.count(predicate: (T) -> Boolean): Int {
var count = 0
for (element in this) if (predicate(element)) checkCountOverflow(++count)
return count
}
复制代码
估计不少小伙伴应该和我同样,很好奇为何中间操做是惰性的?想要获得答案,那就只能去查看源码进行分析了,先看asSequence():
public fun <T> Iterable<T>.asSequence(): Sequence<T> {
return Sequence { this.iterator() }
}
public inline fun <T> Sequence(crossinline iterator: () -> Iterator<T>): Sequence<T> = object : Sequence<T> {
override fun iterator(): Iterator<T> = iterator()
}
复制代码
asSequence()函数会建立一个匿名的Sequence匿名类对象,并将集合的迭代器存储起来,做为本身iterator()方法的返回值。
(能够直接跳过代码,看结果)
#filter函数
public fun <T> Sequence<T>.filter(predicate: (T) -> Boolean): Sequence<T> {
//返回一个FilteringSequence对象
return FilteringSequence(this, true, predicate)
}
internal class FilteringSequence<T>(
private val sequence: Sequence<T>,
private val sendWhen: Boolean = true,
private val predicate: (T) -> Boolean
) : Sequence<T> {
override fun iterator(): Iterator<T> = object : Iterator<T> {
//获取上一个序列的迭代器
val iterator = sequence.iterator()
// -1 for unknown, 0 for done, 1 for continue
var nextState: Int = -1
var nextItem: T? = null
//计算该中间操做的实现(简单说就是在)
private fun calcNext() {
while (iterator.hasNext()) {
val item = iterator.next()
//执行谓词lambda,判断是否符合条件
if (predicate(item) == sendWhen) {
//符合条件则获取元素
nextItem = item
//并修改状态
nextState = 1
return
}
}
nextState = 0
}
override fun next(): T {
//检查机制
if (nextState == -1)
calcNext()
if (nextState == 0)
throw NoSuchElementException()
//获取值,并将状态重置
val result = nextItem
nextItem = null
nextState = -1
@Suppress("UNCHECKED_CAST")
//返回值
return result as T
}
override fun hasNext(): Boolean {
//在上一个序列的迭代器的基础上,进行谓词运算,判断是否有下一个
if (nextState == -1)
calcNext()
return nextState == 1
}
}
}
复制代码
#map函数
public fun <T, R> Sequence<T>.map(transform: (T) -> R): Sequence<R> {
return TransformingSequence(this, transform)
}
internal class TransformingSequence<T, R>
constructor(private val sequence: Sequence<T>, private val transformer: (T) -> R) : Sequence<R> {
override fun iterator(): Iterator<R> = object : Iterator<R> {
//获取上一个序列的迭代器
val iterator = sequence.iterator()
override fun next(): R {
//用函数类型参数进行运算,返回值
return transformer(iterator.next())
}
override fun hasNext(): Boolean {
//沿用上一个序列的迭代器的hasNext()函数
return iterator.hasNext()
}
}
internal fun <E> flatten(iterator: (R) -> Iterator<E>): Sequence<E> {
return FlatteningSequence<T, R, E>(sequence, transformer, iterator)
}
}
复制代码
结合其余中间操做的代码获得的结果是:
(能够直接跳过代码,看结果)
#forEach函数
public inline fun <T> Sequence<T>.forEach(action: (T) -> Unit): Unit {
//迭代进行(注意该this,是指最后一个中端操做返回的Sequence对象)
for (element in this)
action(element)
}
复制代码
#count函数
public inline fun <T> Sequence<T>.count(predicate: (T) -> Boolean): Int {
var count = 0
//迭代进行(注意该this,是指最后一个中端操做返回的Sequence对象)
for (element in this)
if (predicate(element))
checkCountOverflow(++count)
return count
}
复制代码
结合其余末端操做的代码获得的结果是:
总体流程以下所示:
若是在Java的角度上看,就更好理解了。先看一波反编译代码:
public static final void main(@NotNull String[] args) {
List list = CollectionsKt.listOf(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
Sequence $this$forEach$iv = SequencesKt.map(SequencesKt.filter(CollectionsKt.asSequence((Iterable)list), (Function1)null.INSTANCE), (Function1)null.INSTANCE);
int $i$f$forEach = false;
Iterator var4 = $this$forEach$iv.iterator();
while(var4.hasNext()) {
Object element$iv = var4.next();
int it = ((Number)element$iv).intValue();
int var7 = false;
boolean var8 = false;
System.out.println(it);
}
}
复制代码
提取重点代码(1):
//(1)将中间操做对呀的Sequence实例嵌套建立,获得最后一个中间操做的Sequence对象
Sequence $this$forEach$iv = SequencesKt.map(SequencesKt.filter(CollectionsKt.asSequence((Iterable)list), (Function1)null.INSTANCE), (Function1)null.INSTANCE);
复制代码
将这行代码简化:
Sequence listToSequence = CollectionsKt.asSequence((Iterable)list)
Sequence filterSequence = SequencesKt.filter(listToSequence,(Function1)null.INSTANCE)
Sequence mapSequence = SequencesKt.map(filterSequence,,(Function1)null.INSTANCE)
Sequence $this$forEach$iv = mapSequence
复制代码
能够看到,各个中间操做都会产生的Sequence对象,都按照其调用的顺序进行嵌套,最后获得最后一个中间操做的Sequence对象。
提取重点代码(2):
//获取最后一个中间操做的Sequence对象
Iterator var4 = $this$forEach$iv.iterator();
//末端操做迭代迭代器,调用迭代器的next()方法时,将按照中间操做嵌套的瞬间执行中间操做对应的迭代器next方法,获得中间操做的返回值
//。最后一个中间操做的返回值交由末端操做处理
while(var4.hasNext()) {
Object element$iv = var4.next();
//..
}
复制代码
末端操做的for循环会变成while循环,但仍是依据迭代器进行迭代。迭代过程当中不断调用各个中间操做的迭代器,执行中间操做,最后将中间操做获得的值交由末端操做进行处理。
Kotlin的序列使用装饰设计模式,对集合转换的匿名Sequence对象进行动态扩展。所谓装饰设计模式就是在不继承的状况下,使类变得更强大(例如Java的I/O流)。最后在末端操做中调用Sequence的迭代器进行迭代,触发中间操做,并获取其返回值进行处理并输出。