常用高阶函数

Kotlin提供了不少高级语法特性。不过这些函数对于新手来说比较难于读懂,因为很多情况下,我们总会结合着lambda语法来使用。在Kotlin中的源码标准库(Standard.kt)中提供了一些Kotlin扩展的内置函数可以优化kotlin的编码。

常用高阶函数:

  • filter{}:过滤函数。
  • takeWhile{}:按照顺序取数,遇到不符合要求的,就停止。
  • let{}:调用某对象的let函数,则该对象为函数的参数,在函数块内可以通过it指代该对象。let函数另一个作用就是可以避免写一些判断null的操作。返回值为函数块的最后一行或指定return表达式。
  • apply{}:可以直接调用对象的成员变量(方法)。返回值为调用对象自己。apply函数可以和let配合使用,更方便。
  • with(){}:以参数的形式传入,并可直接调用对象的成员变量(方法),无需像let函数一样需要使用it来指代对象。
  • run{}:run函数实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式。适用于let,with函数任何场景。因为run函数是let,with两个函数结合体,准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理。
  • also{}:调用某对象的also函数,则该对象为函数的参数。在函数块内可以通过 it 指代该对象。返回值为该对象自己。also函数的结构实际上和let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。而also函数返回的则是传入对象的本身。一般可用于多个扩展函数链式调用。
  • use{}:通常用于IO操作。即需要关闭资源的操作,使用use函数,能够自动关闭。作用域内可用it指代对象。

it和this的指代:

  • let、also、use都会使用it指代当前对象。
  • with、run、apply都会使用this指代当前对象或者直接省略。

返回值

  • let、with、run均以闭包形式返回。
  • apply、also均返回对象自己。

使用场景:

  • let:适用于处理不为null的操作场景。
  • with:适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上。
  • run:适用于let,with函数任何场景。
  • also:适用于let函数的任何场景,一般可用于多个扩展函数链式调用
  • apply:
  • 适用于run函数的任何场景,一般用于初始化一个对象实例的时候,操作对象属性,并最终返回这个对象。
  • 动态inflate出一个XML的View的时候需要给View绑定数据也会用到。
  • 一般可用于多个扩展函数链式调用。
  • 数据model多层级包裹判空处理的问题。

使用示例:

fun main(args: Array<String>) {
//    testFilter()
//    testLet()
//    testApply()
//    testApplyAndLet()
//    testWith()
//    testRun()
//    testAlso()
//    testReadFile()
//    testUse()
}

fun testFilter() {
    //求0~6的阶乘
    (0..6).map(::factorial).forEach(::println)//map函数是对Array的扩展,是将List<T>转换成 List<R>集合
    //只保留阶乘是期奇数的
    println((0..6).map(::factorial).filter { it % 2 == 1 })//[1, 1]
    //要处于奇数位上的阶乘
    println((0..6).map(::factorial).filterIndexed { index, i -> index % 2 == 1 })//[1, 6, 120]
}

fun testTakeWhile() {
    //根据条件按照顺序取数,遇到不符合要求的,就停止
    println((0..6).map(::factorial).takeWhile { it % 2 == 1 })
}

//阶乘公式 n!=1×2×3×...(n-1)×n
private fun factorial(n: Int): Int {
    if (n == 0) return 1//0的阶乘为1
    return (1..n).reduce { acc, total -> acc * total }
}

fun testLet() {
    val r = findTest()?.let {
        it.aa()
        println(it.a)
        1 + 1
    }
    println(r)//输出2
}

fun testApply() {
    val r = findTest()?.apply {
        // 可以使用Test中的成员变量和方法
        aa()
        println(a)
    }
    println(r?.b)//apply函数返回调用对象本身(即,Test类的对象),因此可以直接调用其成员变量b
}

fun testApplyAndLet() {
    // apply和let一起使用
    findTest()?.apply {
        aa()
        println(a)
        findCeShi()?.let {
            it.cc()
            it.c
            //这里的this是指代调用apply函数的对象
            println(this.b)
        }
    }?.bb()//由于apply返回的事对象自己,因此,此处可以直接调用对象的成员方法或变量
}

fun testWith() {
    //对象作为with函数的参数
    val r = with(findTest()) {
        println(this?.a)
        this?.aa()
        //返回值为函数块的最后一行或指定return表达式。
        this?.b
    }
    println(r)//输出 b参数
}

fun testRun() {
    val r = findTest()?.run {
        println(a)
        aa()
        b
    }
    println(r)//输出 b参数
}

fun testAlso() {
    findTest()?.also {
        it.a
        it.aa()
        it.b
    }?.bb()//also函数返回调用对象本身(即,Test类的对象),因此可以直接调用其成员变量b
}

//普通读取文件
fun testReadFile() {
    val file = File("E:\\blog-note\\test.txt")
    //把文件内容读取进缓冲读取器
    val bufferedReader = BufferedReader(FileReader(file))
    var line: String
    while (true) {
        //当有内容时读取一行数据,否则退出循环
        line = bufferedReader.readLine() ?: break
        println(line)
    }
    bufferedReader.close()//关闭缓冲读取器
}

//使用use函数读取文件,操作结果与上面有一种是一致的。
fun testUse() {
    val file = File("E:\\blog-note\\test.txt")
    //把文件内容读取进缓冲读取器(use方法会自动对BufferedReader进行关闭)
    BufferedReader(FileReader(file)).use {
        var line: String
        while (true) {
            line = it.readLine() ?: break
            println(line)
        }
    }
}

fun findTest(): Test? {
    return Test("a参数", "b参数")
}

data class Test(var a: String, var b: String) {
    fun aa() {
        println("aa is exe!")
    }

    fun bb() {
        println("bb is exe!")
    }
}

fun findCeShi(): CeShi? {
    return CeShi("c参数", "d参数")
}

data class CeShi(var c: String, var d: String) {
    fun cc() {
        println("cc is exe!")
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值