美文网首页禅与计算机程序设计艺术Kotlin专题Kotlin
Kotlin学习之高阶函数和Lambda表达式的基础用法

Kotlin学习之高阶函数和Lambda表达式的基础用法

作者: 程序员丶星霖 | 来源:发表于2017-12-22 09:15 被阅读39次

    Kotlin学习之高阶函数和Lambda表达式的基础用法

    一、定义和调用高阶函数的写法

    kotlin.collections._Arrays.kt中的mapTo()函数的源码如下:

    inline fun <T, R, C : MutableCollection<in R>> Array<out T>.mapTo(destination: C, transformation: (T) -> R): C {
        for (item in this) {
            destination.add(transformation(item))
        }
        return destination
    }
    

    mapTo()是Array<out T>类型的扩展函数,它可以接受两个参数,第一个参数是表示C类型的MutableCollection<in R>,第二个参数是一个(T)->R类型的参数。mapTo()函数会遍历数组中的每个元素,对这个元素调用传入的函数transformation,再将transformation的返回值添加到可变集合destination中,最后返回destination。

    在定义高阶函数时,对于作为参数传入和作为返回值输出的函数,都必须用(参数列表类型)->返回值类型的形式标示清楚,在高阶函数内可以调用作为参数传入的函数。

    要调用高阶函数,可以先定义一个函数,再将函数作为参数传入高阶函数内

    fun main(args: Array<String>) {
        val array = arrayOf(1, 2, 3)
        val destination = mutableListOf<Int>()
        array.mapTo(destination, ::square)
    }
    
    fun square(a: Int) = a * a
    

    定义一个名为square的函数,它接受一个Int类型的参数,返回它的平方根,然后我们用函数引用的形式把它传入mapTo()函数内。这种方法适用于要执行的操作已有函数定义时。

    函数引用是什么?

    • 它的写法是在函数名前加上::用来表示函数对象,而不是调用这个函数。

    调用高阶函数的另一个方法是使用匿名函数或Lambda表达式传入所需的参数

    上面调用mapTo()时,如果没有外部定义square函数,就需要使用匿名函数或Lambda表达式传入我们要执行的操作,如下:

    array.mapTo(destination, fun(a: Int) = a * a)
    

    或者用Lambda表达式代替匿名函数:

    array.mapTo(destination, { a: Int -> a * a })
    

    同时,高阶函数还规定,如果高阶函数的最后一个参数是Lambda表达式,可以把Lambda表达式写在括号外面

    array.mapTo(destination) { a: Int -> a * a }
    

    二、Lambda表达式的写法

    Lambda表达式的完整写法应该是这样的:

    { [参数: 参数类型]…… -> 函数体 }
    

    例如之前的sum函数:

    val sum = { a: Int, b: Int -> a + b}
    

    但是一般情况下,编译器可以推断出参数的类型,一般可以省略参数类型,上面的mapTo()就可以写成:

    array.mapTo(destination) { a -> a * a }
    

    因为array是Array<Int>类型,所以a被自动推导为Int类型,a*a也是Int类型,整个Lambda表达式就是(Int)->Int类型了。

    Lambda还规定,如果Lambda只有一个参数,而且能够推断出它的类型,就可以省略参数说明,只写函数体,在函数题中用it调用这个参数:

    array.mapTo(destination) { it * it }
    

    但是,在使用Lambda表达式时,必须明白it是什么,不能想当然,否则就会出现错误

    val map = mapOf(1 to 2, 3 to 4)
    map.forEach { println(it) }
    

    forEach()函数接受一个(T)->Unit类型的函数,对map中的每一个元素执行传入函数的操作。it是Map.Entry类型,打印结果如下:

    1=2
    3=4
    

    为什么回事这样的呢?

    • 因为forEach()函数里用for(item in this)的形式遍历Map,实际上调用了Map的迭代器,而Map的迭代器迭代的是Map.Entry对象,所以这里的it就是Map.Entry类型,打印时调用的是Map.Entry对象的toString()方法。

    如果只打印map的值,该怎么办?

    1. map.values.foreach{println(it)}
    2. map.foreach{_,value->println(value)}

    学海无涯苦作舟

    我的微信公众号.jpg

    相关文章

      网友评论

        本文标题:Kotlin学习之高阶函数和Lambda表达式的基础用法

        本文链接:https://www.haomeiwen.com/subject/eectgxtx.html