Lambda编程简介

Android  Kotlin  2024年9月26日 am9:01发布2个月前更新 城堡大人
98 0 0

前言

简单记录一下Lambda编程相关知识,方便自己查阅和学习。

这里重点是理解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方法的扩展。

  1. 函数名:pickNumber

  2. 参数:condition: (Int) -> Boolean

  3. 返回值类型:List<Int>

重点,参数是[Lambda表达式当作参数传递],因此重点讲这个。

condition: (Int) -> Boolean
  1. condition:形式参数名,可以是改为其他合法的名字。

  2. (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

参考文章

  1. 《Kotlin从基础到实战》

 历史上的今天

  1. 2021: 洛夫:众荷喧哗(0条评论)
  2. 2021: 舒婷:北戴河之滨(0条评论)
  3. 2020: Android硬件加速(0条评论)
  4. 2019: 林清玄:再加两个苹果(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

XXXX: unexpected operator

最近在用.sh脚本时,明明可以运行的语句,但报错了比如“[: -ne: unexpected operator”因此查询到《解决Linux下编译.sh文件报错 “[: XXXX: unexpected operator”》这篇文章,觉得不错,摘抄于此。使用粗体字语句就可以搞定。3q然后我就表...

查询android机器对应的api版本和硬件相关信息

开发中有时候需要查看Android机器中的硬件信息,我们可以通过如下方式查询。以下部分摘抄于网络,后面有备注参考来源。adb 查询adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利...

[代码片段]GradientTextView渐变的TextView

前言本质上就是通过LinearGradient来实现渐变的正文public class GradientTextView extends androidx.appcompat.widget.AppCompatTextView { public GradientTextView(Context...

AudioTrack简单使用

前言之前也记录过简单记录过AudioTrack的使用,但太久了,而且部分接口已经废弃。今天有空,重新记录一下。主要是提供够自己看的。正文这里主要是播放raw中pcm文件的代码片段,分别做了MODE_STREAM和MODE_STATIC两种方式。MODE_STATIC隐藏内容!付费...

UML类图中属性的可见性简介

UML类图中属性的可见性分为4级public 公用的 :用+ 前缀表示 ,该属性对所有类可见protected 受保护的:用 #  前缀表示,对该类的子孙可见private 私有的:用- 前缀表示,只对该类本身可见package 包的:用 ~ 前缀表示,只对同一包声明的其他类可见...

startActivity源码分析1

前言简单记录一下startActivity()源码的启动过程,主要是过一下流程,细节太多顾不上。下面以Launcher界面启动(startActivity())未启动过的应用为例。这部分主要涉及,启动新的Activity前,系统会让当前Activity[叫Launcher吧]进入onPaus...