一、高阶函数(函数的搬运工)
一句话总结:
高阶函数就是「把函数当快递送进送出 」的函数------可以接收函数作为参数,或者返回一个函数。
典型场景 :比如 map
、filter
这些集合操作,允许你传一个函数告诉它怎么处理数据。
举个现实例子:
你有一个「加工厂」(高阶函数),它能接收不同的「工具函数」来生产不同的产品:
kotlin
// 高阶函数:接收一个函数作为参数
fun 加工厂(原料: String, 工具: (String) -> String): String {
return 工具(原料) // 用传入的「工具」处理原料
}
// 工具1:把原料转大写
val 工具1 = { 原料: String -> 原料.uppercase() }
// 工具2:把原料加前缀
val 工具2 = { 原料: String -> "成品:$原料" }
// 使用:
加工厂("木头", 工具1) // 返回 "木头" → "MU TOU"
加工厂("铁", 工具2) // 返回 "成品:铁"
→ 高阶函数让你能灵活传递不同逻辑,复用代码框架。
二、内联函数(代码的复印机)
一句话总结:
内联函数是「把函数体直接复印到调用处 」的函数------通过 inline
关键字,让编译器把函数代码粘贴到调用的地方,减少函数调用开销(尤其适合高阶函数中的 lambda)。
举个现实例子:
假设你有一个「打印函数」:
kotlin
// 普通函数
fun 打印日志(内容: String) {
println("【日志】$内容")
}
// 调用:
打印日志("用户登录") // 编译后:调用函数,跳转到打印日志的代码
如果改成内联函数:
kotlin
// 内联函数
inline fun 打印日志(内容: String) {
println("【日志】$内容")
}
// 调用:
打印日志("用户登录") // 编译后:直接粘贴 println("【日志】用户登录"),不跳转!
→ 内联函数省去了「跳转执行」的步骤,减少性能损耗。
三、为什么高阶函数要内联?
核心问题:
高阶函数中的 lambda(如 工具: (String) -> String
)在编译时会生成「匿名类对象」,频繁调用会导致内存和性能开销。
内联的解决方案:
用 inline
修饰高阶函数,让 lambda 的代码直接粘贴到调用处,避免创建额外对象。
代码对比:
kotlin
// 普通高阶函数(非内联)
fun 处理数据(数据: String, 处理器: (String) -> String): String {
return 处理器(数据)
}
// 调用时:
处理数据("abc") { it.uppercase() }
// 编译后:每次调用都会创建一个匿名类对象!
// 内联高阶函数
inline fun 处理数据(数据: String, 处理器: (String) -> String): String {
return 处理器(数据)
}
// 调用时:
处理数据("abc") { it.uppercase() }
// 编译后:直接替换为 "abc".uppercase(),没有对象创建!
四、内联函数的优缺点:
优点:
-
性能优化:消除函数调用和 lambda 对象的开销。
-
支持非局部返回 :lambda 中可以直接用
return
退出外层函数。kotlininline fun 遍历列表(list: List<String>, 条件: (String) -> Boolean) { for (item in list) { if (条件(item)) return // 直接退出外层函数 } }
缺点:
- 代码膨胀:函数体被多次粘贴,增大包体积(避免内联大函数)。
- 限制:无法内联递归函数或复杂逻辑的函数。
五、超简记忆法:
- 高阶函数 → "传函数进去干活" (灵活的工具箱)。
- 内联函数 → "直接抄代码" (省时省力的复印机)。
- 组合使用 → "高阶函数内联化" (既灵活又高效)。
总结:
- 高阶函数 让代码更灵活,内联函数让代码更高效。
- 记住:高频调用的高阶函数(尤其是带 lambda 的)一定要内联 (如
map
、filter
等标准库函数都是内联的)。 - 避免滥用内联,只针对性能关键的小函数!