【Kotlin学习】Lambda编程——Lambda表达式和成员引用、集合的函数式API

Kotlin系列之filter、find、any、map、flatMap、takeWhile、reduce、groupBy常见高阶函数 阅读详情

前言

lambda表达式本质上就是可以传递给其他函数的一小段代码,kotlin中大量使用了它们,最差个间的一种lambda用途就是和集合一起工作。

Lambda表达式和成员引用

lambda简介:作为函数参数的代码块

你常常需要表达这样的想法:当一个事件发生的时候运行这个事件处理器。或者把这个操作应用到这个数据结构中所有的元素上。在老版本java中可以用匿名内部类实现,但是太啰嗦了。

函数式编程提供了一种方法:把函数当作值来对待。可以直接传递函数,不需要先声明一个类再传递这个类的实例。它可以高效地直接传递代码块作为函数参数

在java中

在这里插入图片描述

在kotlin中

在这里插入图片描述

这样一句直接代替了java中的匿名内部类的写法

Lambda和集合

假设我们有一个Person的列表,需要找到列表中年龄最大的那个人,在不了解java时我们会去迭代列表返回一个保存好了的变量

而在kotlin中有更好的方法
在这里插入图片描述

在这里插入图片描述

maxByOrNull函数可以在任何集合上调用,且只需要一个实参:一个函数,指定比较哪个值来找到最大元素。花括号中{it.age}就是实现了这个逻辑的lambda。它接受一个集合中的元素作为实参(使用it引用它)并且返回用来比较的值。在上面的例子中,Person是集合元素,用来比较的是存储在age属性中的年龄值。

如果lambda刚好是函数或者属性的委托,可以用成员引用替换

在这里插入图片描述

Lambda表达式的语法

一个lambda把一小段行为进行编码,你能把它当作值到处传递,它可以被独立地声明并存储到一个变量中,但更常见的是直接声明它并传递给函数
表达式始终用花括号包围,实参没有用括号括起来,箭头把实参和函数体隔开
可以把lambda表达式存储在一个变量中,这个变量当作普通函数对待,可通过相应实参调用它

在这里插入图片描述

但这样没什么意义,等价于直接执行lambda函数体中的代码。如果确实需要把一小段代码封闭在一个代码块中,可以使用库函数run来执行传给它的lambda

在前面在集合中寻找年龄最大的人的语句最完整的样子如下

在这里插入图片描述

含义:把花括号的代码片段作为实参传给函数,这个lambda接受一个类型为Person的参数并返回它的年龄

这样写过于啰嗦,kotlin有一个语法约定:如果lambda表达式是函数调用的最后一个实参,它可以放到括号的外边。在这里lambda是唯一的实参,可以放到括号后面

在这里插入图片描述

唯一实参时还可以去掉调用代码中的空括号对

在这里插入图片描述

三种形式含义都是一样的,如果你想传递两个或更多的lambda,不能把超过一个的lambda放到外面,这时使用常规语法来传递它们通常是更好的选择。

把lambda作为命名实参传递

在这里插入图片描述
在这里插入图片描述

重写该调用,把lambda放在括号外

在这里插入图片描述

省略lambda参数类型

在这里插入图片描述

和局部变量一样,如果lambda参数的类型可以被推导出来,就不需要显式指定它。以maxByOrNull为例,其参数类型始终和集合的元素类型相同有,编译器知道你是对一个Person对象的集合调用maxByOrNull函数,所以他能推断lambda参数也会是Person类型

最后的简化,仅在实参名称没有显式指定时这个默认的名称才会生成(如果当前上下文期望的是只有一个参数的lambda且这个参数类型可以推断出来)

在这里插入图片描述

注意!it不能滥用,尤其是在嵌套lambda的情况下,最好显式声明每个lambda的值

如果用变量存储lambda,那么就没有可以推断出参数类型的上下文,所以必须显式指定参数类型

lambda可以包含更多的语句

在这里插入图片描述

在作用域中访问变量

当在函数内声明一个匿名内部类的时候,能够在这个匿名类内部引用这个函数的参数和局部变量,如果在函数内部用lambda也可以访问这个函数的参数,还有在lambda之前定义的局部变量。

在lambda中使用函数参数

在这里插入图片描述

在kotlin中不会仅限于访问final变量,在lambda内部也可以修改这些变量

在lambda中改变局部变量

在这里插入图片描述

kotlin允许在lambda内部访问非final变量甚至修改它们。从lambda内访问外部变量,我们就称这些变量被lambda捕捉

默认情况下,局部变量的生命期被限制在声明这个变量的函数中,但如果它被lambda捕捉了,使用这个变量的代码可以被存储并稍后再执行。当你捕捉final变量时,他的值和使用这个值的lambda代码一起存储,对非final变量来说,它的值被封装在一个特殊的包装器中,这样你就可以改变这个值,而对这个包装器的引用会和lambda代码一起存储

捕捉可变变量:实现细节

java只允许你final变量,当你想捕捉可变变量的时候,要么声明一个单元素的数组,其中存储可变值,要么创建一个包装类的实例,其中存储要改变的值的引用

在kotlin中显式使用这些技术

在这里插入图片描述

在这里插入图片描述

在实际代码中不需要包装器,可以直接修改这个变量,上方就是原理,当你捕捉了一个可变变量时,它的值被作为包装类的一个实例而被存储下来,包装类变量是final类型可以被轻易捕捉,然而实际值被存储在其字段中,并且可以在lambda内修改

注意!如果lambda被用作事件处理器护着用在其他异步执行的情况,对局部变量的修改只会在lambda执行的时候发生

在这里插入图片描述

这个函数始终返回0,我们无法观察到值的变化,因为监听器处理器是在函数返回后调用的,这个函数的正确实现应把点击次数存储在函数外依然可以访问的地方,而不是存储在函数的局部变量中。

成员引用

如果你想要当作参数传递的代码已经被定义成了函数…

kotlin和java8一样,把函数转换成一个值,你就可以传递他,使用::运算符来转换

在这里插入图片描述

这被称为成员引用,它简明地创建一个调用单个方法或者访问单个属性的函数值,双冒号把类名称与你要引用的成员隔开。不管你引用的是函数还是属性,都不要在成员引用的名称后面加括号。成员引用和调用该函数的lambda具有一样的类型,所以可以互换使用。

还可以引用顶层函数 形式如下
::函数名,run(::a)此时省略了类名称,::函数名被当作实参传递给库函数run,它会调用相应的函数。

如果lambda要委托给一个接收多个参数的函数,提供成员引用代替它将会非常方便

在这里插入图片描述

这个lambda委托给send参数,也可以用成员引用代替

可以用构造方法引用存储或者延期执行创建类实例的动作。构造方法引用的形式是在双冒号后指定类名称

在这里插入图片描述

还可以用同样的方式引用扩展函数,即使他不是Person类的成员,但还是可以访问,和访问实例的成员一样

绑定引用

在kotlin1.1版本中支持绑定成员引用,它允许你使用成员引用语法捕捉特定实例对象上的方法引用

在这里插入图片描述

在1.1之前你需要显式写出lambda{p.age}而不是使用绑定成员引用p::age

集合的函数式API

基础:filter和map

它们形成了集合操作的基础,很多集合操作都是借助它们表达的

filter函数遍历集合并选出应用给定lambda后会返回true的那些元素,输出结果的集合中只包含输入集合中那些满足判断式的元素,但它不会改变这些元素。

在这里插入图片描述

map函数对集合中的每一个元素应用给定的函数并把结果收集到一个新集合

在这里插入图片描述

返回一个它们的平方集合

打印一个姓名列表并改为成员引用

image.png

把多次这样的调用链接起来,下图为输出年龄大于30岁的人的名字

在这里插入图片描述

当需要这个分组中所有年龄最大的人的名字时

在这里插入图片描述

注意!这段代码对每个人都会去找一遍最大年龄,而不是只计算一次最大年龄

改进:把计算最大年龄用变量提取出来,然后再用其和每一个人比较

all、any、count、find:对集合应用判断式

另一种常见的任务是检查集合中所有元素是否都符合某个条件(或是否存在符合的元素),它们通过all和any函数表达。conut函数检查有多少元素满足判断式,find函数返回第一个符合条件的元素。

在这里插入图片描述

先定义一个判断式isless18,若你对所有的元素是否满足判断式感兴趣,那就可以使用all,如果只需要检查集合中至少存在一个匹配的元素就使用any

如果你想知道有多少个元素满足了判断式,则使用count

在这里插入图片描述

要找到一个满足判断式的元素,使用find函数,若有多个匹配的,返回第一个,没有一个满足返回null。同义方法firstOrNull

groupBy:把列表转换成分组的map

若你需要把所有元素按照不同的特征划分成不同的分组,比如把人按年龄分组

在这里插入图片描述

在这里插入图片描述

每一个分组都是存储在一个列表中,结果的类型就是Map<Int,List< Person>>

使用成员引用把字符串按照首字母分组

在这里插入图片描述

flatMap和flatten:处理嵌套集合中的元素

在这里插入图片描述

每本书都可能有一个或者多个作者,可以统计处图书馆中的所有作者的set

在这里插入图片描述

这样子books集合中书籍的所有作者的set便创建成功,toSet()会移除重复元素

在这里插入图片描述

flatMap做了两件事
根据作为实参给定的函数对集合中的每个元素做变换(或者说映射),然后把多个列表合并(平铺)成一个列表

例子

在这里插入图片描述

在这里插入图片描述

第一步映射,把abc和def都映射成单个字符,第二步把它们平铺,结合在一起成为一个列表

字符串上的toList函数把它转换成字符列表

若你不需要做任何变换,只是需要平铺一个集合,可以使用flatten函数

在这里插入图片描述

在这里插入图片描述

华为OD机试双机位C卷-组装新的数组(Py/Java/C/C++/Js/Go) 华为OD机试(机考)双机位C卷 【组装新的数组】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试 - 组装新的数组。 阅读详情

相关推荐

TI IWR 6843 ISK 毫米波雷达开箱测试

TI IWR6843 ISK毫米波雷达上手体验,教程十分详细,对于新手很友好。

qq_57061492的博客 4036

Kotlin Lambda

always in curly braces {x: Int, y: Int -> x + y} if a lambda is the last argument in a function call, it can be placed after the parentheses list.maxByOrNull ({ it: Person -> it.age }) list.maxByOrNull () { it: Person -> it.age } if the lambda is.

weiwang_wang的博客 272

手把手教你用Kokoro-82M-v1.1-zh搭建本地TTS服务(含WebSocket接口)

本文详细介绍了如何使用Kokoro-82M-v1.1-zh模型搭建本地TTS服务,包括环境配置、模型部署、WebSocket接口实现及性能优化。通过实战指南,开发者可以快速掌握本地部署TTS系统的关键技术,提升语音交互应用的开发效率。

weixin_30776273的博客 183

Kotlin入门笔记(九)集合的函数式编程 API(上)

前言:本教程最好在有JAVA的基础下进行学习 例题: 如何在一个水果集合内找到单词最长的哪个水果? 或许你会这样写: val list = listOf("Apple","Banana","Pear","Grape","Watermelon") var maxLengthFruit = "" for (fruit in list) { if(fruit.length > maxLengthFruit.length) { maxLengthFruit = fruit

m0_46745664的博客 1659

从CAD到完美网格:HyperMesh几何清理全流程指南(2023最新版)

本文详细介绍了2023最新版HyperMesh在几何清理和网格划分方面的全流程操作指南。从CAD导入、几何修复到中面提取和网格生成,系统性地分享了实战验证的解决方案,帮助工程师高效处理复杂几何体,提升有限元模型质量。特别针对汽车和航空航天领域的常见问题,提供了智能化工具和优化技巧。

weixin_29306011的博客 227

GEE AI: 利用 Satellite Embedding 语义搜索快速识别研究区目标斑块

摘要 本文介绍了一种基于Google Earth Engine的遥感语义搜索技术,利用Satellite Embedding数据集快速识别目标地物。该方法通过将光谱信息转化为高维向量,在武汉市的案例中展示了如何:1)定义研究区和样本点;2)加载预处理的Embedding数据;3)计算向量相似度;4)结合面积过滤优化结果。相比传统监督分类,该技术具有响应快速(无需模型训练)、抗季节干扰和精准界定等优势,特别适用于森林碳储量监测和土地利用检测等应用场景。文中提供了完整的GEE代码实现流程,包括样本定义、相似度计

此星光明博客 625

Kotlin入门学习(非常详细),从零基础入门到精通,看完这一篇就够了(1)

和Java中的接口定义类似。

2401_84254057的博客 1421

104报文解析工具

可选择包含报文的文本文件或日志文件进行解析,可选择按条数范围或时间范围,输出结果可以在报文解析显示区,也可以输出到文件。可以对文本内容的报文文件进行高级分析,包括遥信遥测等通讯数据的具体信息,通讯帧的统计,通讯次数的统计,各种错误的分析,报文的定位功能,传输的文件具体内容等。输入完成后点击工具栏的解析报文按钮或使用右键菜单的解析就可以对报文进行解析。在报文输入区输入待解析报文并解析后,解析结果就显示在报文解析显示区和报文定位展示区及报文定位条目区。当有多条报文解析后,可以通过报文列表树具体定位某条报文。

XZHOUMIN的博客 5951

《Kotlin从小白到大牛》第17章:Kotlin中函数式编程API

第17章 Kotlin中函数式编程API 为了提供对函数式编程的支持,Kotlin在集合和数组中提供了一些高阶函数,它们的参数和返回类型都是函数类型。因为集合和数组它们都是数据的容器,即按照某种算法实现的数据结构,这些数据在这些函数中“流动”最后输出结果。集合和数组中的这些高阶函数构成了Kotlin函数式编程API,本章介绍这些API。 17.1 函数式编程API与链式调用 函数操控的是数据,数据是放在集合或数组中的,而集合和数组在数学中计算可以分为:遍历、排序、过滤、映射、聚合等等。因此凡是支持函数式编程

weixin_38072116的博客 457

YOLOv8改进 | 注意力篇 | YOLOv8引入EMAttention(EMA)注意力

具体来说,除了对全局信息进行编码以重新校准每个并行分支中的通道权重之外,还通过跨维度交互来进一步聚合两个并行分支的输出特征,以捕获像素级的成对关系。3. 跨空间学习:除了在每个并行子网络中建立局部的跨通道交互外,EMA模块还通过跨空间学习方法融合了两个并行子网络的输出特征图。到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

tsg6698的博客 896

【CSP-S 提高组】考试大纲集合

【CSP-S提高组】考试大纲集合

weixin_42596089的博客 7255

Kotlin学习笔记五:Lambda编程

Kotlin学习笔记 Kotlin学习笔记一:Kotlin基础 Kotlin学习笔记二:Kotlin的类型系统 Kotlin学习笔记三:函数 Kotlin学习笔记四:类,对象,接口 Lambda编程 Lambda表达式和成员引用 Lambda表达式就是可以传递给其它函数一小段代码,在Java中通常用匿名内部类来实现, 函数式编程把函数当代一值传递,而不用先声明一个类,再实现方法,传递这个类的实...

苟浩的博客 965

基于YOLOv13+CBAM注意力机制

本教程详细介绍了CBAM注意力机制的原理及其在YOLOv13中的集成方法。CBAM通过通道注意力和空间注意力两个模块,动态调整特征权重以增强模型性能。通道模块利用池化操作和共享MLP生成通道权重,空间模块则通过池化和卷积生成空间权重。教程提供了在YOLOv13中实现CBAM的具体步骤,包括模块代码定义、模型配置修改等关键环节,帮助开发者在目标检测任务中提升模型表现。

FJN110的博客 305

Kotlin中的lambda函数式API编程

函数接收两个参数,第一个参数是任意类型的对象,第二个参数是lambda表达式,在lambda表达式中会提供第一个参数的上下文,并用最后一行作为返回值。当我们用Kotlin调用Java方法时,如果这个方法只接受一个Java单抽象方法接口参数就可以换成函数式API。函数非常常用,可以把集合的每个元素都映射成另一个值,规则则是由接受的lambda表达式决定。这个函数,该函数工作原理是接收一个lambda表达式,根据传入的条件来找到最大值。的优秀推导类型的机制,可以直接省略类型,然后当参数只有一个时,可以直接用。

zzx_0826的博客 1512

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Kotlin系列六:从集合谈Kotlin中的Lambda编程

目录 一 集合的函数式API 1.1.1 List 1.1.2Set 1.1.3Map 二 集合的函数式API 2.1集合的函数式API的推导 2.1 集合常用函数式API 2.1.1 map函数 2.1.2filter函数 2.1.3any和all函数 三 Java函数式API的使用 一 集合的函数式API 集合的函数式API是学习Lambda编程的绝佳示例。 传统意义上的集合主要就是List和Set,再广泛一点的话,像Map这样的键值对数据结构也可以包含进来。 L...

许进进的博客 5074

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Kotlin 中 Lambda的使用 一、入门 集合的函数式API中Lambda表达式的使用

很多高级编程语言很早就支持Lambda编程,java从JDK1.8开始支持Lambda编程语法,而kotlin从第一版开始就支持Lambda编程。本章从集合的函数式API的使用做的Kotlin中Lambda入门。

old_land的博客 1317

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

【Kotlin】高阶函数和Lambda

Kotlin天然支持了部分函数式特性。我们可以在一个函数内部定义一个局部函数。 抽象和高阶函数 在我们以往熟悉的编程中,过程限制为只能接收数据为参数由于我们经常会遇到一些同样的程序设计模式能够用于不同的过程,比如一个包含了正整数的列表,需要对它的元素进行各种转换操作,例如对所有元素都乘以3,或者都除以2。我们就需要提供一种模式,同时接收这个列表及不同的元素操作过程,最终返回一个新的列表为了把这种类似的模式描述为相应的概念,我们就需要构造出一种更加高级的过程,表现为:接收一个或多个过程为参数,或者以一个过程作

xoliu的博客 2484

Kotlin教程(六)Lambda编程

写在开头:本人打算开始写一个Kotlin系列的教程,一是使自己记忆和理解的更加深刻,二是可以分享给同样想学习Kotlin的同学。系列文章的知识点会以《Kotlin实战》这本书中顺序编写,在将书中知识点展示出来同时,我也会添加对应的Java代码用于对比学习和更好的理解。 Kotlin教程(一)基础 Kotlin教程(二)函数 Kotlin教程(三)类、对象和接口 Kotlin教程(四)可空...

Hubert的博客 1249

Kotlin-Lambda编程,集合map,filter,any,all函数的使用(第一行代码Kotlin学习笔记3)

目录1. 集合1.1 集合的创建和遍历1.2 集合函数式API使用2. Lambda编程2.1 Lambda详解2.2 集合常用的函数式APImap()filter()any() 和 all() 函数2.3 Java 常用的函数式API 1. 集合 1.1 集合的创建和遍历 Kotlin中专门提供了内置函数来初始化集合 使用如下代码可以初始化一个List集合: val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape") 但我们需要注意的

liuhp的博客 2876

Kotlin之集合的函数式API(Lambda)

集合的函数式 API 有很多种,我们只重点学习函数式 API 的结构,也就是 Lambda 表达式的语法结构 要求:在集合中找出名字最长的那个值: fun main() { val list = listOf("a", "ab", "abc", "bc") var maxLength = "" for (name in list) { if (name.length > maxLength.length) { maxLength = na

非猿 446

Android第一行代码——快速入门 Kotlin 编程(2.6 Lambda 编程)

函数的功能非常强大,它可以按照我们的需求对集合中的元素进行任意的映射转换,上面只是一个简单的示例而已。这样我们就将 Lambda 表达式的语法结构和几个常用的函数式 API 的用法都学习完了,虽然集合中还有许多其他函数式 API,但是只要掌握了基本的语法规则,其他函数式 API 的用法只要看一 看文档就能掌握了,相信这对你来说并不是难事。函数是最常用的一种函数式 API,它用于将集合中的每个元素都映射成一个另外的值,映射的规则在 Lambda 表达式中指定,最终生成一个新的集合。

fhbxts的博客 1166

《Kotlin实战》-第05章:Lambda编程

《Kotlin实战》-第05章:Lambda编程

crazyf2015的博客 626

【编程语言】Kotlin快速入门 - 集合与Lambda

Java工程师Kotlin快速入门之集合与Lambda

XuanRan的博客 4121

Android开发——Kotlin语法之Lambda表达式

Kotlin中的Lambda表达式

qq_43903506的博客 1090

Kotlin中的Lambda编程

1.集合的创建与遍历 传统意义上的集合主要是List和Set,再广泛一点的话,像Map这样的键值对数据结构也可以包含进来。List,Set和Map再Java中都是接口,List主要的实现类是ArrayList和LinkedList,Set的主要实现类是HashSet,Map的主要实现类的HashMap。 比如现在创建一个包含许多水果名称的集合,在java中我们会首先创建一个ArrayList的实例,然后将水果的名称一个个添加到集合中。在kotlin也可以这么做。

ChenYiRan123456的博客 1232

kotlin学习笔记——Lambda表达式

最近在学郭神的《第三行代码》,大部分内容出自于此,另外加上我自己的一些总结和体会,记此学习笔记,若有歧义,欢迎指出,一起学习进步! 定义 直白的说,Lambda就是一小段可以作为参数传递的代码。 一般向某个函数传参都只能是变量,而Lambda可以传一段代码。 类似python中的map、reduce函数,允许传入Lambda表达式,ketlin的集合中也有很多类似的函数式API ,如map() filter() maxByOrNull()等(maxBy()已被弃用) 虽然kotlin对传入的代码长度没有

LiePy的博客 3244
上一篇: 【Kotlin学习】类、对象和接口——带非默认构造方法或属性的类、数据类和类委托、object关键字
下一篇: 【Kotlin学习】Lambda编程——序列、使用Java函数式接口、with和apply函数
Panic  Lin
博客等级 码龄6年 81粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值