Lambda表达式
//输出最长字母的String
val list = listOf<String>("Apple", "Banana", "Pear", "Grape")
val maxLength = list.maxBy({ fruit: String -> fruit.length })
println(maxlength)
- 当lambda表达式是一个函数的最后一个参数时,可以将lambda表达式移到函数括号外面
val maxLength = list.maxBy(){ fruit: String -> fruit.length }
- 当lambda表达式是函数唯一一个参数时,可以将函数的括号省略
val maxLength = list.maxBy{ fruit: String -> fruit.length }
- 根据Kotlin的类型推导机制,lambda表达式中的参数大多数情况下不必声明类型
val maxLength = list.maxBy{ fruit -> fruit.length }
- 当lambda表达式中的参数列表只有一个参数时,也不必声明参数名,使用it代替
val maxLength = list.maxBy{ it.length }
- lambda表达式中的最后一行代码会自动作为返回值
高阶函数
-
定义:如果一个函数接受另一个函数作为参数,或者返回值的类型是另一个函数,这个函数就叫做高阶函数
-
Kotlin定义的函数类型:
- -> 左边声明函数类型接受的参数,多参数可用逗号隔开,如果没有参数写一对括号表示
- ->右边声明函数的返回类型,如果没有返回值就使用Unit,相当于Java里的void
(String, Int) -> Unit
例如:
fun example(func: (String, Int) -> Unit) { func("hello", 123) }
-
用途:高阶函数允许让函数类型的参数决定函数的执行逻辑。即时同一个高阶函数,只要传入不用的函数类型参数,那么它的执行逻辑和返回的结果可能完全不同。
例如:/** * 第三个参数是一个接收俩个整形参数并且返回值也是整型的参数类型函数。 * 在num1AndNUm2()函数中,没有进行任何具体运算操作,而是将num1和num2参数传给了第三个函数类型参数, * 并获取它的返回值,最终将得到的返回值返回 * @param num1 Int * @param num2 Int * @param operation Function2<Int, Int, Int> * @return Int */ fun num1AndNUm2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int { val result = operation(num1, num2) return result }
//引用 val num1 = 100 val num2 = 80 val result1 = num1AndNUm2(num1, num2) { n1, n2 -> n1 + n2 } val result2 = num1AndNUm2(num1, num2) { n1, n2 -> n1 - n2 } println("result1 is $result1") println("result2 is $result2") -> result1 is 180 -> result2 is 20
例如:
/** * ClassName. 语法结构表示函数类型是定义在哪个类当中的。 * 这里将函数定义在StringBuilder类中我们可以调用build函数是传入的lambda可以自动拥有StringBuilder的上下文, * 这也是apply函数的实现方式 * @receiver StringBuilder * @param block [@kotlin.ExtensionFunctionType] Function1<StringBuilder, Unit> * @return StringBuilder */ fun StringBuilder.build(block: StringBuilder.() -> Unit): StringBuilder { block() return this }
//引用 val list = listOf<String>("Apple", "Banana", "Pear", "Grape") val result = StringBuilder().build { append("Start eating fruits.\n") for (fruit in list) { append(fruit).append("\n") } append("Ate all fruits") } println(result.toString()) -> Start eating fruits. Apple Banana Pear Grape Ate all fruits
-
内联函数
- 背景:Kotlin高阶函数的实现是使用lambda表达式在底层被转换成了匿名类的方式,我们每调用一次lambda表达式,都会创建一个新的匿名类实例,会造成额外的内存和性能开销
- Kotlin解决方法:内联函数(inline)
- 原理:Kotlin编译器会将内联函数中的代码在编译的时候自动替换到调用它的地方。
- 过程:
(a)首先,Kotlin编译器会将lambda表达式中的代码转换到函数类型参数调用的地方
(b)再将内联函数中的全部代码替换到函数调用的地方
(c)最终的代码被替换成下图