首页 / Android 入门教程 / 高阶函数与 Lambda

Android 入门教程

高阶函数与 Lambda

本教程共 100 篇 · 第 17 篇 · 更新于 2026-07-28 · 约 8 分钟阅读

AndroidAndroid 入门教程Kotlin高阶函数Lambdainline函数类型

17. 高阶函数与 Lambda

本节目标:理解函数类型、掌握 Lambda 写法、知道 inline 函数为什么能优化性能、熟练用集合操作符处理数据。

什么是高阶函数

高阶函数就是接收函数作为参数、或者返回函数的函数。Kotlin 里函数是「一等公民」,能像变量一样传来传去。

最典型的例子是集合操作符:

val nums = listOf(1, 2, 3, 4)
nums.filter { it > 2 }          // { it > 2 } 就是个 Lambda
nums.map { it * 10 }
nums.forEach { println(it) }

filter 接收一个「判断函数」作为参数,这个函数对每个元素求值返回 Boolean。把「做什么」作为参数传给「怎么遍历」,就是高阶函数的精髓。

函数类型

Kotlin 用 (参数类型) -> 返回类型 表示函数类型:

val add: (Int, Int) -> Int = { a, b -> a + b }
val isEven: (Int) -> Boolean = { it % 2 == 0 }
val greet: (String) -> Unit = { name -> println("Hello, $name") }

println(add(1, 2))           // 3
println(isEven(4))           // true
greet("Android")             // Hello, Android
  • (Int, Int) -> Int 表示接收两个 Int 返回 Int 的函数。
  • 无参数写成 () -> Int
  • 无返回值写成 (Int) -> Unit

类型别名

复杂函数类型用 typealias 起个短名:

typealias ClickHandler = (View) -> Unit

fun setClickListener(handler: ClickHandler) { /* ... */ }

Lambda 表达式

Lambda 是匿名函数的简写:{ 参数 -> 函数体 }

val sum = { a: Int, b: Int -> a + b }
println(sum(1, 2))      // 3

it 隐式参数

Lambda 只有一个参数时,可以省略参数声明,用 it 引用:

val square: (Int) -> Int = { it * it }

末尾 Lambda 约定

函数最后一个参数是函数类型时,Lambda 可以提到括号外:

// 标准写法
list.fold(0, { acc, n -> acc + n })

// 约定写法,更清晰
list.fold(0) { acc, n -> acc + n }

如果函数只有 Lambda 一个参数,括号都能省:

list.forEach { println(it) }
Tip
  • 这个约定让 Kotlin 写 DSL(如 Compose)特别自然。Column { Text("hi") } 这种写法就是末尾 Lambda。

函数作为参数

fun performOperation(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

val result = performOperation(3, 4) { x, y -> x * y }   // 12
val sum = performOperation(3, 4) { x, y -> x + y }      // 7

策略模式不用定义接口了,直接传函数。

函数作为返回值

fun multiplier(factor: Int): (Int) -> Int {
    return { n -> n * factor }      // 捕获 factor
}

val double = multiplier(2)
val triple = multiplier(3)
println(double(5))     // 10
println(triple(5))     // 15

返回的 Lambda 捕获了外层的 factor,这种「闭包」是函数式编程的核心特性。

inline 内联函数

高阶函数每次调用会创建 Lambda 对象,有性能开销。inline 关键字让编译器把函数体直接展开到调用处,消除对象创建。

inline fun repeat(times: Int, action: (Int) -> Unit) {
    for (i in 0 until times) action(i)
}

repeat(3) { println("第 $it 次") }

标准库的 letrunapplyforEachfiltermap 都是 inline 的,所以用这些操作符不会增加额外对象开销。

Note
  • 自定义高阶函数如果在性能敏感路径(循环、列表处理),加 inline。但 inline 会让编译产物变大,不要滥用。

noinline 与 crossinline

inline 函数里某些函数参数不想内联用 noinline;Lambda 里不能 return(non-local return)时用 crossinline。这两个进阶场景遇到再查,日常很少手写。

集合操作符进阶

第 15 章介绍过基本操作符,这里补充几个组合用法。

map / filter / flatMap

data class User(val name: String, val emails: List<String>)

val users = listOf(
    User("张三", listOf("a@x.com", "b@x.com")),
    User("李四", listOf("c@x.com"))
)

// 所有邮箱
val allEmails = users.flatMap { it.emails }
// [a@x.com, b@x.com, c@x.com]

// 邮箱数 >= 2 的用户
val multiEmail = users.filter { it.emails.size >= 2 }

// 用户名转大写
val names = users.map { it.name.uppercase() }

flatMap 把「列表的列表」拍平成单层列表。

fold / reduce

val sum = listOf(1, 2, 3, 4).fold(0) { acc, n -> acc + n }    // 10
val product = listOf(1, 2, 3, 4).fold(1) { acc, n -> acc * n } // 24

val sum2 = listOf(1, 2, 3, 4).reduce { acc, n -> acc + n }    // 10,无初始值

fold 有初始值,reduce 用第一个元素当初始值。

groupBy / associate

val users = listOf(
    User("张三", 18, "北京"),
    User("李四", 20, "上海"),
    User("王五", 18, "北京")
)

// 按城市分组
val byCity = users.groupBy { it.city }
// {北京=[张三, 王五], 上海=[李四]}

// 按年龄分组,只取名字
val namesByAge = users.groupBy({ it.age }, { it.name })
// {18=[张三, 王五], 20=[李四]}

partition

按条件拆成两个列表:

val (minors, adults) = users.partition { it.age < 18 }

zip

两个列表按位置配对:

val names = listOf("张三", "李四")
val ages = listOf(18, 20)
val pairs = names zip ages        // [(张三, 18), (李四, 20)]
val map = names.zip(ages).toMap() // {张三=18, 李四=20}

Android 实战

回调用 Lambda 替代接口

Java 风格的回调接口:

// Java 风格
interface OnDataLoaded {
    fun onSuccess(data: List<Item>)
    fun onError(error: Throwable)
}

fun loadData(callback: OnDataLoaded) { /* ... */ }

Kotlin 风格,直接用函数类型:

fun loadData(
    onSuccess: (List<Item>) -> Unit,
    onError: (Throwable) -> Unit
) { /* ... */ }

loadData(
    onSuccess = { items -> showData(items) },
    onError = { e -> showError(e.message ?: "未知错误") }
)

Compose 里到处是高阶函数

@Composable
fun UserList(users: List<User>, onUserClick: (User) -> Unit) {
    LazyColumn {
        items(users) { user ->
            UserRow(user, onClick = { onUserClick(user) })
        }
    }
}

// 调用
UserList(users = userList) { user ->
    // 点击处理,Lambda 提到括号外
    navigateToDetail(user.id)
}

自定义 inline 工具

inline fun measureTime(block: () -> Unit): Long {
    val start = System.currentTimeMillis()
    block()
    return System.currentTimeMillis() - start
}

val cost = measureTime {
    // 耗时操作
    doHeavyWork()
}
println("耗时 $cost ms")

小结

高阶函数接收或返回函数。函数类型用 (A) -> B 表示。Lambda 是 { 参数 -> 体 },单参数用 it,末尾 Lambda 可提括号外。inline 内联消除对象开销。集合操作符(map/filter/flatMap/fold/groupBy/zip)是数据处理利器。Android 里用 Lambda 替代回调接口,Compose 全靠高阶函数构建。下一节学协程基础。