kotlin高阶函数源码阅读记录

kotlin源码刚开始阅读的时候还是挺难理解的,下面对自己看过的一些函数源码作下总结:

forEach

public inline fun  Iterable.forEach(action: (T) -> Unit): Unit {
    for (element in this) action(element)
}

调用示范

val list = listOf(1,2,3,4,5)
list.forEach({arg : Int -> println(arg)})

T就是list的类型,按照上面调用的方法就是Int类型,传入的参数是action: (T) -> Unit,就是一个带有Int类型参数无返回值的函数,{arg : Int -> println(arg)}刚好就是一个这样的函数.
这里补充一下,通常{arg : Int -> println(arg)}过于臃肿,kotlin提供更简单的写法,利用类型推导,可以省略Int类型

list.forEach({arg -> println(arg)})

如果只有一个参数可以不需要声明,直接用it代替

list.forEach({println(it)})

这种参数传递最后一个参数可以提到()外面,并且省略(),如下

list.forEach{println(it)}

接下来看执行的代码

public inline fun  Iterable.forEach(action: (T) -> Unit): Unit {
    for (element in this) action(element)   //循环迭代,执行传入的action
}

reduce

public inline fun  Iterable.reduce(operation: (acc: S, T) -> S): S {
    val iterator = this.iterator()
    if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
    var accumulator: S = iterator.next()
    while (iterator.hasNext()) {
        accumulator = operation(accumulator, iterator.next())
    }
    return accumulator
}

调用示范

val list = listOf(1,2,3,4,5)
list.reduce { acc : Int, i ->  i + acc}

源码中S, T类型到底是什么,整个执行过程是怎样的呢?
Iterable 是list,那么T就是Int类型,在operation: (acc: S, T) -> S 中T是Int类型,那S又是什么类型呢?S实际上可以自定义,但是必须注意到函数前面有一个声明,这意味着S必须是T的父类或者就是T类型,在上面调用中完整的写法其实是
list.reduce { acc : Int, i -> i + acc}
那么这个S其实也是Int类型.搞清楚类型过后,接下来看执行的代码

public inline fun  Iterable.reduce(operation: (acc: S, T) -> S): S {
    val iterator = this.iterator()  //this是指list,iterator是list的迭代器
    if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
    var accumulator: S = iterator.next()    //累加值,保存list中第一个变量
    while (iterator.hasNext()) {
        accumulator = operation(accumulator, iterator.next())   //开始执行operation,这个具体怎么执行看传入的函数了,大概就是accumulator和iterator.next()执行某种算法后赋值给accumulator
    }
    return accumulator
}

fold

这个函数和reduce非常类似,区别就是有一个初始值而且R类型可以任意指定

public inline fun  Iterable.fold(initial: R, operation: (acc: R, T) -> R): R {
    var accumulator = initial
    for (element in this) accumulator = operation(accumulator, element)
    return accumulator
}

调用方法

(0..6).fold(5,{acc, i -> acc +i })

显然在这种情况下T类型是迭代器的类型, R一个可以任意指定的类型,在上面调用中T和R都是Int类型.接下来看一下代码注释

public inline fun  Iterable.fold(initial: R, operation: (acc: R, T) -> R): R {
    var accumulator = initial   //赋值初始值
    for (element in this) accumulator = operation(accumulator, element) //迭代,并执行传入的operation
    return accumulator
}

另外前面提到R实际上可以任意指定,可以看看下面

(0..6).fold(StringBuilder(),{ acc : StringBuilder, i -> acc.append(i) }).toString()

filter

public inline fun  Iterable.filter(predicate: (T) -> Boolean): List {
    return filterTo(ArrayList(), predicate)
}

调用示范

val array = listOf(1,2,3)
array.filter { arg : Int -> arg % 2 == 0 }

在这种情况下T就是Int类型,返回一个boolean值. arg % 2就是判断依据

public inline fun > Iterable.filterTo(destination: C, predicate: (T) -> Boolean): C {
    for (element in this) if (predicate(element)) destination.add(element)
    return destination
}

在里面还调用了一个filterTo(ArrayList(), predicate)
filterTo很好解释

public inline fun > Iterable.filterTo(destination: C, predicate: (T) -> Boolean): C {
    for (element in this) if (predicate(element)) destination.add(element)  
    return destination
}

传入destination实际就是ArrayList(),根据具体的调用T就是Int类型,那么这里C也是Int类型,然后predicate是一个条件判断,
为true的情况下会添加到destination上面.

takeWhile

public inline fun  Iterable.takeWhile(predicate: (T) -> Boolean): List {
    val list = ArrayList()
    for (item in this) {
        if (!predicate(item))
            break
        list.add(item)
    }
    return list
}

实际调用

val array = listOf(1,2,3,4,5,6)
array.takeWhile { it % 2 == 0 }

更具调用情况这里T就是int, predicate就是it % 2 == 0,predicate作为判断条件决定是否添加到新创建的list里面然后返回.

let

public inline fun  T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

实际调用

"3".let { null }

根据实际调用情况T就是String, R就是null类型. 这个函数的主要作用实际上就是一个类型转换.

apply

public inline fun  T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

实际调用

class Person{
    fun work(){
        print("")
    }
}
fun applyT(){
    findPerson().apply {
        this.work()
        print("调用完成")
    }
}

block: T.() -> Unit实际上是一个T类型的扩展函数并且是无返回值, apply函数里面也就是调用这个扩展函数,然后返回自己.

with

public inline fun  with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

with其实和apply还挺类似,apply的调用,而with是作为参数传入, 最后返回R类型,下面来看一个with的应用场景

fun writeToFile(){
    val str = "my name is jay"
    val bw = BufferedWriter(FileWriter("hello.txt"))
    with(bw){
        write(str)
        close()
    }
}

use

public inline fun  T.use(block: (T) -> R): R {
    var exception: Throwable? = null
    try {
        return block(this)
    } catch (e: Throwable) {
        exception = e
        throw e
    } finally {
        when {
            apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
            this == null -> {}
            exception == null -> close()
            else ->
                try {
                    close()
                } catch (closeException: Throwable) {
                    // cause.addSuppressed(closeException) // ignored here
                }
        }
    }
}

这个调用类型必须是Closeable,它省去了调用close()的过程(已经封装到了use里面)

fun writeToFile(){
    val str = "my name is jay"
    val bw = BufferedWriter(FileWriter("hello.txt"))
    bw.use { it.write(str) }
}

你可能感兴趣的:(kotlin高阶函数源码阅读记录)