目录
前言
简单记录一下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
参考文章