2026-06-18 我对Kotlin的Lambda的一点理解
我就不加目录了,也不会涉及很多代码,就根据我个人的理解简单聊聊,算是给未来健忘的自己写个小tip。
这个寄吧lambda表达式,我当初学Java的时候就没怎么学明白,到了Kotlin更是一头雾水。
今天下午的时候,看着看着就有些悟了。
首先明确几个规定:
- Kotlin函数的参数可以是一个函数体(lambda表达式);
- 当函数体参数是最后一个参数的时候,可以将函数体从括号中移出去;
- 当被调用的函数只有一个参数且该参数是函数体参数时,括号可以省略。
函数体作为参数传给另一个函数?为什么要这么设计?
其实,这个设计不是为了方便被调用的函数,而是为了方便我们自己。通过这个函数体参数,被调用的函数得到了什么?其实只得到了“返回值”,那既然他只需要返回值,那我们为什么不在外面将这个函数体参数定义完整,然后再使用一个变量接收返回值传给被调用函数呢?
傻逼吧,刚刚已经说了这是为了方便我们自己,看一下这种情况:
val list = listOf("123","12345","1","45","456106","635","51575")
var maxLenStr = ""
for (str in list){
if(str.length > maxLenStr.length){
maxLenStr = str
}
}
仅仅是为了获得最长的字符串就要这么麻烦,再看看下面这种形式:
val list = listOf("123","12345","1","45","456106","635","51575")
val maxLenStr = list.maxByOrNull { it.length }
这就很方便了,那么究竟是怎么回事呢?追进去看一下:
public inline fun <T, R : Comparable<R>> Iterable<T>.maxByOrNull(selector: (T) -> R): T? {
val iterator = iterator()
if (!iterator.hasNext()) return null
var maxElem = iterator.next()
if (!iterator.hasNext()) return maxElem
var maxValue = selector(maxElem)
do {
val e = iterator.next()
val v = selector(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
} while (iterator.hasNext())
return maxElem
}
可以看到,我们传入的函数体被当成了一个函数,名为selector,这个函数接收it为参数,并返回it.length。
it是什么呢?其实就是list本身,将函数调用者自身传入函数中作为参数,这也是Kotlin的强大之处。
可以看到,maxByOrNull函数的实际作用就是先判断list是否为空,如果是空就直接返回空,然后判断是否只有一个元素,如果是的话就直接返回这一个。不止一个的话就不断迭代判断。
相当于Kotlin将这些可能存在的繁琐语句都包装实现了。
所以回顾一下我刚开始说的,被调用的函数实际上只是需要函数体参数的返回值,我们可以将他视作一种条件,可以抽象出以下模型:
- 函数还是原本的作用:接收输入→处理→提供输出;
- lambda相当于一个协助函数工作的小工具,以自己的返回值协助函数完成相关功能。
在上面这个例子中,
- 函数作用是根据某种条件选出使该条件值最大的一个元素;
- lambda的返回值告诉函数:条件是元素的字符串长度
那有的人又要问了:这不就是封装了一个函数么?那我用Java封装一个函数不也是一样的效果?
所以说呢,学而不思则罔。
注意我前面说的,lambda以自己的返回值协助函数完成相关功能。这也就是说,返回值是关键,我们无论提供什么返回值,该函数都能利用它来最终返回最大的一个元素。
那我们是不是漏了什么东西?没错,lambda只有返回值吗?显然不是啊,函数只是需要lambda的返回值而已,没有强制lambda除了返回值外不能有其他的语句,所以我们可以针对性地定制对元素的操作,这是封装函数所做不了的,举个例子:
我们想要在寻找最长字符串的时候,看一下每一个元素究竟是多长:
val list = listOf("123","12345","1","45","456106","635","51575")
val maxLenStr = list.maxByOrNull {
println(it.length)
it.length
}
println(maxLenStr)
也就是说,相较于封装成函数,使用lambda的方式是可以对函数高度定制的。
这就使得开发者可以写出功能更加丰富的应用了。
更多推荐
所有评论(0)