目录
前言
简单记录一下Lambda编程相关知识,方便自己查阅和学习。
这里重点是理解lambda作为函数参数的使用。
正文
Lambda表达式
使用函数式编程可以减少代码的重复,提高程序的开发效率。
Lambda表达式相对于普通函数有些区别,普通函数有4种返回值类型,即无参数无返回值、无参数有返回值、有参数无返回值、有参数有返回值。
而Lambda表达式只有两种返回值类型,即无参数有返回值、有参数有返回值。
无参数有返回值
在定义无参数有返回值的Lambda表达式时,只需要将函数体写在“{}”中,函数体可以是表达式或语句块。
语法格式如下:
- { 函数体 }
比如
- {println()}
那如何调用呢?
在调用Lambda表达式时,只是在Lambda表达式后添加了“()”,“()”就代表了调用该表达式。
语法格式如下:
- {函数体}()
比如
- {println()}()
有参数有返回值
在定义有参数有返回值的Lambda表达式时,需要指定参数名称以及参数类型,参数之间使用英文“,”分隔。
Lambda表达式中的“->”用于表示箭头,用于指定参数或数据的指向,具体语法格式如下:
- //一个参数
- {参数名:参数类型-> 函数体 }
- //两个参数
- {参数名:参数类型,参数名2:参数类型-> 函数体 }
调用时,跟无参的一样,后面添加(),但这里需要传入参数值
- {参数名:参数类型,参数名2:参数类型-> 函数体 }(参数值1,参数值2)
定义了一个函数,并将该函数赋值给变量sum,
- //计算3+4的结果
- var sum = { a:Int, b:Int -> a+b }(3,4)
-
- //或者
- //sumFun是一个函数
- var sumFun = { a:Int, b:Int -> a+b }
- sumFun(3,4)
Lambda表达式返回值
Lambda表达式所表示的函数都是有返回值的,而且不管方法体里面的语句执行多少条,返回值的类型和返回值都是由方法体中最后一条语句决定的。
返回值看最后以后得结果。
- var sum = {
- a: Int, b: Int ->
- 100
- }(1,2)
- Log.d(TAG, "test: $sum ")
返回值为
- test: 100
高阶函数的使用
Lambda表达式还可以作为函数的实际参数或者返回值存在,而这种声明,在Kotlin中叫做高阶函数。
将Lambda表达式作为参数或返回值,会大大地简化程序开发时的代码,提高程序开发效率。
函数作为参数使用
Lambda表达式,除了定义在方法的内部,还可以作为函数的实参,这种做法拓宽了我们的编程思维。
下面举例来说
定义
- private fun IntRange.pickNumber(condition: (Int) -> Boolean): List<Int> {
- val resultList = mutableListOf<Int>()
- for (i in this) {
- if (condition(i)) {
- resultList.add(i)
- }
- }
- return resultList
- }
这里是对IntRange方法的扩展。
函数名:pickNumber
参数:condition: (Int) -> Boolean
返回值类型:List<Int>
重点,参数是[Lambda表达式当作参数传递],因此重点讲这个。
- condition: (Int) -> Boolean
condition:形式参数名,可以是改为其他合法的名字。
(Int) -> Boolean:形式参数类型。这里是一个函数类型,函数的参数是Int类型,函数的返回值是Boolean类型。
搞懂上面的意思就很容易明白pickNumber函数的功能。
调用
- var list = 1..20
- var newList = list.pickNumber({ x: Int -> x % 2 == 0 })
- Log.d(TAG, "test: $newList")
输出的结果
- test: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
函数作为参数优化
当Lambda表达式作为函数参数使用时,还有3种优化形式,这3种优化形式分别是省略小括号、将参数移动到小括号外面、使用it关键字。
省略小括号
如果函数只有一个参数,且这个参数类型是一个函数类型,则在调用函数时可以去掉函数名称后面的小括号。
这个就是上面我
- var list = 1..20
- var newList1 = list.pickNumber({ x: Int -> x % 2 == 0 })
- Log.d(TAG, "test: $newList1")
- //等同上面,可以省略()
- var newList2 = list.pickNumber { x: Int -> x % 2 == 0 }
- Log.d(TAG, "test: $newList2")
将参数移动到小括号外面
如果一个函数有多个参数,但是最后一个参数类型是函数类型,那么在调用函数时,可以将最后一个参数从括号中移出,并且去掉参数之间的符号“,”。
- private fun IntRange.pickNumber(ignoreNumber: Int, condition: (Int) -> Boolean): List<Int> {
- val resultList = mutableListOf<Int>()
- for (i in this) {
- if (ignoreNumber != i && condition(i)) {
- resultList.add(i)
- }
- }
- return resultList
- }
调用
- var list = 1..20
- var newList1 = list.pickNumber(10, { x: Int -> x % 2 == 0 })
- Log.d(TAG, "test: $newList1")
- //等同上面
- var newList2 = list.pickNumber(10) { x: Int -> x % 2 == 0 }
- Log.d(TAG, "test: $newList2")
输出的结果一样,少了10
- test: [2, 4, 6, 8, 12, 14, 16, 18, 20]
第二个就是把函数体移到()之外。
使用it关键字
无论函数包含多少个参数,如果其中有参数是函数类型,并且函数类型满足只接收一个参数的要求,可以用it关键字代替函数的形参以及箭头。
- var list = 1..20
- var newList1 = list.pickNumber(10) { x: Int -> x % 2 == 0 }
- Log.d(TAG, "test: $newList1")
- var newList2 = list.pickNumber(10) { it % 2 == 0 }
- Log.d(TAG, "test: $newList2")
函数作为返回值
函数不仅可以作为参数使用,还可以作为返回值使用。
- //声明枚举,定义两种类型
- private enum class USER {
- NORMAL, VIP
- }
- // 声明价钱方法
- private fun getPrice(userType: USER): (Double) -> Double {
- //判断类型,是否需要打折
- if (userType == USER.NORMAL) {
- return { it }
- }
- return { price -> 0.88 * price }
- }
调用
- var price1 = getPrice(USER.NORMAL)(100.0)
- var price2 = getPrice(USER.VIP)(100.0)
- Log.d(TAG, "test price1 : $price1")
- Log.d(TAG, "test price2 : $price2")
返回值
- test price1 : 100.0
- test price2 : 88.0