Skip to content

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 }   // 12

Lambda 就是匿名函数,语法 { 参数 -> 函数体 }。Kotlin 标准库里到处都是高阶函数——集合的 mapfilterforEach 都是。

二、集合操作:告别 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 结果

函数参数返回值典型场景
letitlambda 结果空安全 + 类型转换
applythis对象本身对象初始化
runthislambda 结果配置 + 计算
alsoit对象本身附加操作(日志等)
withthislambda 结果对同一对象多次操作

记忆口诀:参数 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 协程详解》。