Kotlin 的高阶函数和 let/apply/run 这些作用域函数天天写,但"它们到底怎么区分、什么时候用哪个"一直有点混。这篇把高阶函数和 lambda 讲清楚,重点攻克面试高频、最容易混的作用域函数。
一、高阶函数:把函数当参数传
高阶函数 = 接受函数作参数,或返回函数的函数。这是函数式编程的核心:
kotlin
// 高阶函数:第二个参数 operation 是一个函数
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
// 传 lambda 进去
calculate(3, 4) { x, y -> x + y } // 7
calculate(3, 4) { x, y -> x * y } // 12Lambda 就是匿名函数,语法 { 参数 -> 函数体 }。Kotlin 标准库里到处都是高阶函数——集合的 map、filter、forEach 都是。
二、集合操作:告别 for 循环
高阶函数 + 集合操作,是 Kotlin 比 Java 爽的地方:
kotlin
val users = listOf(User("BinMaker", 18), User("Yu", 20), User("Hi", 16))
// 链式操作:过滤 + 转换 + 归约
val adultNames = users
.filter { it.age >= 18 } // 过滤:18 岁以上
.map { it.name } // 转换:只取名字
// ["BinMaker", "Yu"]
val totalAge = users.sumOf { it.age } // 求和
val max = users.maxByOrNull { it.age } // 找最大filter/map/reduce/sumOf 这些配合 lambda,替代了 Java 里冗长的 for 循环 + 临时变量。
三、作用域函数:let/apply/run/also/with
作用域函数是面试高频、也最容易混的——它们长得像,区别只在两点:参数是 it 还是 this、返回是对象本身还是 lambda 结果。
| 函数 | 参数 | 返回值 | 典型场景 |
|---|---|---|---|
| let | it | lambda 结果 | 空安全 + 类型转换 |
| apply | this | 对象本身 | 对象初始化 |
| run | this | lambda 结果 | 配置 + 计算 |
| also | it | 对象本身 | 附加操作(日志等) |
| with | this | lambda 结果 | 对同一对象多次操作 |
记忆口诀:参数 it 的是 let/also,this 的是 apply/run/with;返回对象本身的是 apply/also,返回结果的是 let/run/with。
逐个看代码:
kotlin
// let:参数 it,返回结果 —— 空安全 + 转换
val len = name?.let { it.length } // name 非空才执行,返回长度
// apply:参数 this,返回对象 —— 初始化对象
val user = User().apply {
name = "BinMaker" // this 是 user,直接改字段
age = 18
} // 返回 user 本身
// run:参数 this,返回结果 —— 配置 + 计算
val desc = user.run {
"$name 今年 $age 岁" // 返回字符串
}
// also:参数 it,返回对象 —— 附加操作(不改变对象)
val u = User().also {
println("创建了 $it") // 打个日志,返回的仍是 user
}
// with:参数 this,返回结果 —— 对同一对象多次操作(非扩展函数)
val info = with(user) {
"名字: $name, 年龄: $age"
}四、怎么选(速查)
- 要空安全处理 →
let - 要初始化对象 →
apply - 要配置并得到结果 →
run - 要附加操作不打断链(日志、校验) →
also - 要对对象做一堆事返回结果 →
with
其实不用死记,抓住两点就行:想不想要 this(改对象内部用 apply/run/with),想不想返回结果(要结果用 let/run/with)。
小结
- 高阶函数 = 函数当参数传,lambda 是匿名函数
- 集合操作
map/filter/sumOf替代 for 循环 - 作用域函数区别两点:参数
it/this、返回对象/结果 - let(空安全转换)、apply(初始化)、run(配置+结果)、also(附加)、with(多次操作)
想了解 Kotlin 的空安全、扩展函数、数据类这些基础特性,看《Kotlin 核心特性》;想了解 Kotlin 的并发王牌,看《Kotlin 协程详解》。
