Skip to content

Kotlin 高阶函数详解 🎯

Android 面试必考 Kotlin 高阶函数,包含函数类型、Lambda 参数、返回函数、内联高阶函数、标准库高阶函数等核心知识点


目录

  1. 函数类型
  2. 高阶函数定义
  3. Lambda 作为参数
  4. 返回函数
  5. 内联高阶函数
  6. 标准库高阶函数
  7. 面试考点汇总

1. 函数类型

1.1 基础语法

函数类型表示可以存储和传递的函数引用:

kotlin
// 基本函数类型
val sum: (Int, Int) -> Int = { a, b -> a + b }

// 无参数函数
val greet: () -> String = { "Hello" }

// 无返回值函数
val printHello: () -> Unit = { println("Hello") }

// 可空函数类型
val optionalFunc: (() -> Unit)? = null

// 带接收者的函数类型
val block: StringBuilder.() -> Unit = {
    append("Hello")
    append(" World")
}

1.2 函数类型的变量

kotlin
// 声明函数类型变量
var operation: (Int, Int) -> Int

// 赋值
operation = { a, b -> a + b }
operation = { a, b -> a - b }
operation = { a, b -> a * b }

// 调用
val result = operation(3, 4)  // 7

// 函数类型作为属性
class Calculator {
    var operation: (Int, Int) -> Int = { a, b -> a + b }
    
    fun calculate(a: Int, b: Int): Int {
        return operation(a, b)
    }
}

// 使用
val calc = Calculator()
calc.calculate(3, 4)  // 7

calc.operation = { a, b -> a * b }
calc.calculate(3, 4)  // 12

1.3 函数类型的完整语法

kotlin
// 完整语法:(参数类型,...) -> 返回类型
val func1: (Int) -> Int = { x -> x * 2 }

// 多个参数
val func2: (Int, Int) -> Int = { a, b -> a + b }

// 带命名参数(调用时使用)
val func3: (a: Int, b: Int) -> Int = { a, b -> a + b }

// 可空参数和返回
val func4: (Int?) -> String? = { num -> num?.toString() }

// 带接收者的函数类型
val func5: Int.(Int) -> Int = { x -> this + x }

// 使用
val result = 5.func5(3)  // 8,this 是 5

// 挂起函数类型
val suspendFunc: suspend () -> String = {
    withContext(Dispatchers.IO) {
        "Result from IO"
    }
}

1.4 函数类型与匿名函数

kotlin
// Lambda 表达式
val sum1: (Int, Int) -> Int = { a, b -> a + b }

// 匿名函数
val sum2: (Int, Int) -> Int = fun(a, b): Int {
    return a + b
}

// 匿名函数可以指定返回类型
val sum3 = fun(a: Int, b: Int): Int {
    return a + b
}

// 带接收者的匿名函数
val block: StringBuilder.() -> Unit = fun() {
    this.append("Hello")  // this 是 StringBuilder
}

// 使用
val sb = StringBuilder()
sb.block()

1.5 函数类型的实际场景

kotlin
// 1. 策略模式
class DataProcessor {
    var filterStrategy: (Int) -> Boolean = { true }
    var transformStrategy: (Int) -> Int = { it }
    
    fun process(data: List<Int>): List<Int> {
        return data.filter(filterStrategy).map(transformStrategy)
    }
}

// 使用
val processor = DataProcessor()

// 只处理偶数
processor.filterStrategy = { it % 2 == 0 }

// 加倍
processor.transformStrategy = { it * 2 }

val result = processor.process(listOf(1, 2, 3, 4, 5))
// [4, 8]

// 2. 回调函数
class Button {
    var onClick: (() -> Unit)? = null
    
    fun click() {
        onClick?.invoke()
    }
}

// 使用
val button = Button()
button.onClick = {
    println("Button clicked!")
}
button.click()

// 3. 配置 DSL
class Dialog {
    var title: String = ""
    var message: String = ""
    var positiveButton: String = "OK"
    
    fun show() {
        println("Dialog: $title - $message")
    }
}

fun dialog(configure: Dialog.() -> Unit): Dialog {
    return Dialog().apply(configure)
}

// 使用
dialog {
    title = "提示"
    message = "确定要删除吗?"
    positiveButton = "删除"
}.show()

2. 高阶函数定义

2.1 基础概念

高阶函数是接受函数作为参数或返回函数的函数:

kotlin
// 接受函数作为参数
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// 使用
val result = operate(3, 4) { a, b -> a + b }  // 7

// 返回函数
fun getMultiplier(factor: Int): (Int) -> Int {
    return { x -> x * factor }
}

// 使用
val double = getMultiplier(2)
println(double(5))  // 10

2.2 高阶函数的多种形式

kotlin
// 形式 1:单个函数参数
fun <T> List<T>.forEach(action: (T) -> Unit) {
    for (element in this) {
        action(element)
    }
}

// 形式 2:多个函数参数
fun <T> List<T>.filterMap(
    predicate: (T) -> Boolean,
    transform: (T) -> String
): List<String> {
    return this.filter(predicate).map(transform)
}

// 形式 3:函数参数有默认值
fun <T> List<T>.process(
    filter: (T) -> Boolean = { true },
    transform: (T) -> T = { it }
): List<T> {
    return this.filter(filter).map(transform)
}

// 形式 4:返回函数
fun createCounter(): () -> Int {
    var count = 0
    return { count++ }
}

// 使用
val counter = createCounter()
println(counter())  // 0
println(counter())  // 1
println(counter())  // 2

2.3 尾随 Lambda 参数

当最后一个参数是函数时,可以将其放在括号外:

kotlin
// 定义
fun <T> List<T>.customMap(transform: (T) -> Int): List<Int> {
    return this.map(transform)
}

// 调用 - 尾随 Lambda
val numbers = listOf(1, 2, 3)
val result = numbers.customMap {
    it * 2
}

// 多个参数时
fun <T> List<T>.process(
    prefix: String,
    transform: (T) -> String
): List<String> {
    return this.map { "$prefix${transform(it)}" }
}

// 调用
val result = numbers.process("Number: ") {
    it.toString()
}

2.4 高阶函数实战

kotlin
// 1. 重试机制
suspend fun <T> retry(
    times: Int = 3,
    delayMs: Long = 1000,
    operation: suspend () -> T
): T {
    var lastException: Exception? = null
    
    repeat(times) { attempt ->
        try {
            return operation()
        } catch (e: Exception) {
            lastException = e
            if (attempt < times - 1) {
                delay(delayMs)
            }
        }
    }
    
    throw lastException ?: Exception("Unknown error")
}

// 使用
val result = retry(times = 3, delayMs = 2000) {
    api.loadData()
}

// 2. 超时处理
suspend fun <T> withTimeout(
    timeoutMs: Long,
    block: suspend () -> T
): T {
    return withTimeout(timeoutMs) {
        block()
    }
}

// 3. 事务处理
fun <T> transaction(
    begin: () -> Unit,
    commit: () -> Unit,
    rollback: () -> Unit,
    operation: () -> T
): T {
    begin()
    return try {
        val result = operation()
        commit()
        result
    } catch (e: Exception) {
        rollback()
        throw e
    }
}

// 4. 测量执行时间
fun <T> measureTime(block: () -> T): Pair<T, Long> {
    val start = System.currentTimeMillis()
    val result = block()
    val duration = System.currentTimeMillis() - start
    return result to duration
}

// 使用
val (result, time) = measureTime {
    expensiveOperation()
}
println("Result: $result, Time: ${time}ms")

3. Lambda 作为参数

3.1 Lambda 语法回顾

kotlin
// 完整语法
val sum = { a: Int, b: Int -> a + b }

// 类型推断
val sum: (Int, Int) -> Int = { a, b -> a + b }

// 单个参数可以使用 it
val double: (Int) -> Int = { it * 2 }

// 无参数
val greet: () -> String = { "Hello" }

// 多行 Lambda
val complex = { x: Int, y: Int ->
    val sum = x + y
    val product = x * y
    sum + product
}

3.2 Lambda 作为参数的模式

kotlin
// 模式 1:单一 Lambda 参数
fun <T> List<T>.forEach(action: (T) -> Unit) {
    for (element in this) action(element)
}

// 调用
listOf(1, 2, 3).forEach {
    println(it)
}

// 模式 2:Lambda 是最后一个参数
fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
    return this.map(transform)
}

// 调用 - Lambda 放在括号外
val result = listOf(1, 2, 3).map {
    it * 2
}

// 模式 3:多个 Lambda 参数
fun <T> List<T>.filterMap(
    predicate: (T) -> Boolean,
    transform: (T) -> String
): List<String> {
    return this.filter(predicate).map(transform)
}

// 调用
val result = listOf(1, 2, 3, 4, 5).filterMap(
    { it % 2 == 0 },
    { "Number: $it" }
)

// 模式 4:带接收者的 Lambda
class Builder {
    var name: String = ""
    var age: Int = 0
}

fun build(block: Builder.() -> Unit): Builder {
    return Builder().apply(block)
}

// 调用
val person = build {
    name = "张三"
    age = 25
}

3.3 Lambda 参数的命名约定

kotlin
// 单个参数使用 it(标准库约定)
list.map { it * 2 }

// 多个参数或需要清晰语义时命名
list.map { number -> number * 2 }
list.forEachIndexed { index, value ->
    println("$index: $value")
}

// 成对解构
map.forEach { (key, value) ->
    println("$key: $value")
}

// 忽略不需要的参数
list.forEach { _ ->
    println("Item")
}

3.4 Lambda 与协程

kotlin
// suspend Lambda 作为参数
suspend fun fetchData(
    url: String,
    onSuccess: suspend (String) -> Unit,
    onError: suspend (Throwable) -> Unit
) {
    try {
        val result = withContext(Dispatchers.IO) {
            // 网络请求
            "data"
        }
        onSuccess(result)
    } catch (e: Exception) {
        onError(e)
    }
}

// 使用
lifecycleScope.launch {
    fetchData(
        url = "https://api.example.com/data",
        onSuccess = { data ->
            updateUI(data)
        },
        onError = { error ->
            showError(error.message)
        }
    )
}

// 返回 suspend 函数
fun createDataLoader(): suspend (String) -> String {
    return { url ->
        withContext(Dispatchers.IO) {
            // 加载数据
            "data from $url"
        }
    }
}

3.5 Lambda 捕获变量

kotlin
// Lambda 可以捕获外部变量
fun createCounter(): () -> Int {
    var count = 0
    return {
        count++
        count
    }
}

// 使用
val counter = createCounter()
println(counter())  // 1
println(counter())  // 2
println(counter())  // 3

// 捕获 this
class MyClass {
    private var value = 10
    
    fun getPrinter(): () -> Unit {
        return {
            println(value)  // 捕获外部类的 value
        }
    }
}

// 明确指定 this
class Outer {
    val value = "Outer"
    
    inner class Inner {
        val value = "Inner"
        
        fun print() {
            val block: () -> Unit = {
                println(value)           // Inner.value
                println(this@Inner.value) // Inner.value
                println(this@Outer.value) // Outer.value
            }
            block()
        }
    }
}

4. 返回函数

4.1 基础语法

kotlin
// 返回 Lambda
fun getAdder(x: Int): (Int) -> Int {
    return { y -> x + y }
}

// 使用
val add5 = getAdder(5)
println(add5(3))  // 8

// 返回匿名函数
fun getMultiplier(factor: Int): (Int) -> Int {
    return fun(x): Int {
        return x * factor
    }
}

// 简化写法
fun getMultiplier2(factor: Int) = { x: Int -> x * factor }

4.2 返回带接收者的函数

kotlin
// 返回带接收者的函数
fun createBuilder(): StringBuilder.() -> Unit {
    return {
        append("Hello")
        append(" ")
        append("World")
    }
}

// 使用
val sb = StringBuilder()
sb.createBuilder()()
println(sb.toString())  // "Hello World"

// 更实用的例子
fun <T> createFilter(predicate: (T) -> Boolean): (T) -> Boolean {
    return predicate
}

// 使用
val isEven = createFilter { it % 2 == 0 }
println(listOf(1, 2, 3, 4).filter(isEven))  // [2, 4]

4.3 工厂函数模式

kotlin
// 1. 策略工厂
interface SortStrategy {
    fun <T : Comparable<T>> sort(list: List<T>): List<T>
}

class QuickSortStrategy : SortStrategy {
    override fun <T : Comparable<T>> sort(list: List<T>): List<T> {
        // 快速排序实现
        return list.sorted()
    }
}

class MergeSortStrategy : SortStrategy {
    override fun <T : Comparable<T>> sort(list: List<T>): List<T> {
        // 归并排序实现
        return list.sorted()
    }
}

fun getSortStrategy(algorithm: String): SortStrategy {
    return when (algorithm) {
        "quick" -> QuickSortStrategy()
        "merge" -> MergeSortStrategy()
        else -> QuickSortStrategy()
    }
}

// 2. 验证器工厂
typealias Validator<T> = (T) -> Boolean

fun <T> createValidator(
    vararg validations: Validator<T>
): Validator<T> {
    return { value ->
        validations.all { it(value) }
    }
}

// 使用
val emailValidator: Validator<String> = { it.contains("@") }
val lengthValidator: Validator<String> = { it.length >= 5 }

val combinedValidator = createValidator(emailValidator, lengthValidator)
println(combinedValidator("test@example.com"))  // true
println(combinedValidator("short"))  // false

// 3. 转换器工厂
fun <T, R> createMapper(transform: (T) -> R): (List<T>) -> List<R> {
    return { list -> list.map(transform) }
}

// 使用
val stringMapper = createMapper { it.toString() }
println(stringMapper(listOf(1, 2, 3)))  // ["1", "2", "3"]

4.4 柯里化(Currying)

kotlin
// 柯里化:将多参数函数转换为单参数函数链
fun add(a: Int): (Int) -> Int {
    return { b -> a + b }
}

// 使用
val add5 = add(5)
println(add5(3))  // 8

// 直接调用
println(add(5)(3))  // 8

// 通用柯里化
fun <P1, P2, R> curry(f: (P1, P2) -> R): (P1) -> (P2) -> R {
    return { p1 -> { p2 -> f(p1, p2) } }
}

// 使用
val sum = { a: Int, b: Int -> a + b }
val curriedSum = curry(sum)
println(curriedSum(5)(3))  // 8

// 三个参数的柯里化
fun <P1, P2, P3, R> curry(f: (P1, P2, P3) -> R): (P1) -> (P2) -> (P3) -> R {
    return { p1 -> { p2 -> { p3 -> f(p1, p2, p3) } } }
}

4.5 部分应用(Partial Application)

kotlin
// 部分应用:固定部分参数,返回新函数
fun multiply(a: Int, b: Int, c: Int): Int = a * b * c

// 固定第一个参数
fun multiplyBy2(b: Int, c: Int) = multiply(2, b, c)

// 使用 Lambda 实现部分应用
fun <P1, P2, P3, R> partial1(
    f: (P1, P2, P3) -> R,
    p1: P1
): (P2, P3) -> R {
    return { p2, p3 -> f(p1, p2, p3) }
}

// 使用
val multiplyBy2Partial = partial1(::multiply, 2)
println(multiplyBy2Partial(3, 4))  // 24

5. 内联高阶函数

5.1 inline 关键字的作用

kotlin
// 普通高阶函数
fun <T> List<T>.forEach(action: (T) -> Unit) {
    for (element in this) action(element)
}

// 编译后(伪代码)
// 1. 创建 Lambda 对象
// 2. 调用 forEach 方法
// 3. Lambda 对象在循环中被调用

// 内联高阶函数
inline fun <T> List<T>.forEach(action: (T) -> Unit) {
    for (element in this) action(element)
}

// 编译后(伪代码)
// 直接展开 Lambda 内容
for (element in this) {
    // Lambda 内容直接在这里
    println(element)
}

5.2 noinline 和 crossinline

kotlin
// noinline:禁止特定 Lambda 参数内联
inline fun test(
    inlineParam: () -> Unit,
    noinline noInlineParam: () -> Unit
) {
    inlineParam()  // 内联
    noInlineParam()  // 不内联,可以作为对象传递
    
    // 可以将 noInlineParam 传递给其他函数
    executeLater(noInlineParam)
}

fun executeLater(action: () -> Unit) {
    // 延迟执行
    action()
}

// crossinline:禁止非局部返回
inline fun test(crossinline block: () -> Unit) {
    val runnable = Runnable {
        block()  // 不能在这里 return
    }
    Thread(runnable).start()
}

// ❌ 错误:crossinline 禁止非局部返回
// fun example() {
//     test {
//         return  // ❌ 错误:不能从外部函数返回
//     }
// }

// ✅ 正确:使用标签返回
fun example() {
    test {
        return@example  // ✅ 从 example 返回
    }
}

5.3 内联函数的实际场景

kotlin
// 1. 资源管理(use)
inline fun <T : Closeable, R> T.use(block: (T) -> R): R {
    var exception: Throwable? = null
    try {
        return block(this)
    } catch (e: Throwable) {
        exception = e
        throw e
    } finally {
        try {
            close()
        } catch (e: Throwable) {
            if (exception == null) throw e
            exception.addSuppressed(e)
        }
    }
}

// 使用
FileInputStream("file.txt").use { fis ->
    // 自动关闭,无需 finally
    val content = fis.readBytes()
}

// 2. 同步锁
inline fun <T> Any.synchronized(block: () -> T): T {
    return kotlin.synchronized(this, block)
}

// 使用
val lock = Any()
val result = lock.synchronized {
    // 线程安全操作
    sharedData
}

// 3. 运行作用域
inline fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}

inline fun <T, R> T.run(block: T.() -> R): R {
    return block()
}

inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}

inline fun <T> T.also(block: (T) -> Unit): T {
    block(this)
    return this
}

5.4 reified 泛型

内联函数可以使用 reified 泛型,在运行时获取类型信息:

kotlin
// 普通泛型(类型擦除)
fun <T> isInstanceOf(obj: Any): Boolean {
    // return obj is T  // ❌ 错误:类型信息在运行时被擦除
    return false
}

// reified 泛型
inline fun <reified T> isInstanceOf(obj: Any): Boolean {
    return obj is T  // ✅ 正确:内联后可以获取类型
}

// 使用
println(isInstanceOf<String>("Hello"))  // true
println(isInstanceOf<Int>(42))  // true
println(isInstanceOf<String>(42))  // false

// 实际应用:过滤类型
inline fun <reified T> List<*>.filterIsInstance(): List<T> {
    return this.filterIsInstance<T>()
}

// 使用
val list = listOf(1, "hello", 2, "world", 3)
val strings = list.filterIsInstance<String>()  // ["hello", "world"]
val ints = list.filterIsInstance<Int>()  // [1, 2, 3]

// 实际应用:启动 Activity
inline fun <reified T : Activity> Context.startActivity() {
    val intent = Intent(this, T::class.java)
    startActivity(intent)
}

// 使用
context.startActivity<DetailActivity>()

5.5 内联类的性能优化

kotlin
// 内联类(值类)- Kotlin 1.5+
@JvmInline
value class UserId(val value: String)

@JvmInline
value class Email(val value: String)

// 编译后直接是 String,没有对象开销
fun sendEmail(userId: UserId, email: Email) {
    // userId 和 email 在运行时就是 String
}

// 内联类可以有方法
@JvmInline
value class Percent(val value: Int) {
    fun toDouble(): Double = value / 100.0
    operator fun plus(other: Percent): Percent {
        return Percent(this.value + other.value)
    }
}

// 使用
val p1 = Percent(50)
val p2 = Percent(30)
val p3 = p1 + p2  // Percent(80)
println(p3.toDouble())  // 0.8

6. 标准库高阶函数

6.1 集合操作函数

kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 转换操作符
numbers.map { it * 2 }           // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
numbers.mapIndexed { i, v -> i * v }  // [0, 2, 6, 12, 20, ...]
numbers.flatMap { listOf(it, it * 2) }  // [1, 2, 2, 4, 3, 6, ...]

// 过滤操作符
numbers.filter { it % 2 == 0 }   // [2, 4, 6, 8, 10]
numbers.filterNot { it % 2 == 0 } // [1, 3, 5, 7, 9]
numbers.filterIndexed { i, v -> i % 2 == 0 }  // [1, 3, 5, 7, 9]

// 取/舍操作符
numbers.take(3)                  // [1, 2, 3]
numbers.takeLast(3)              // [8, 9, 10]
numbers.takeWhile { it < 5 }     // [1, 2, 3, 4]
numbers.drop(3)                  // [4, 5, 6, 7, 8, 9, 10]
numbers.dropWhile { it < 5 }     // [5, 6, 7, 8, 9, 10]

// 查找操作符
numbers.find { it > 5 }          // 6
numbers.findLast { it > 5 }      // 10
numbers.indexOfFirst { it > 5 }  // 5
numbers.indexOfLast { it > 5 }   // 9

// 判断操作符
numbers.any { it > 5 }           // true
numbers.all { it > 0 }           // true
numbers.none { it < 0 }          // true
numbers.contains(5)              // true

6.2 分组和分区

kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6)

// 分组
numbers.groupBy { it % 2 }
// {1=[1, 3, 5], 0=[2, 4, 6]}

numbers.groupBy({ it % 2 }, { it * 2 })
// {1=[2, 6, 10], 0=[4, 8, 12]}

// 分区
numbers.partition { it % 2 == 0 }
// ([2, 4, 6], [1, 3, 5])

// 切片
numbers.chunked(2)
// [[1, 2], [3, 4], [5, 6]]

numbers.chunked(3)
// [[1, 2, 3], [4, 5, 6]]

// 窗口
numbers.windowed(3)
// [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6]]

numbers.windowed(3, step = 2)
// [[1, 2, 3], [3, 4, 5], [5, 6]]

6.3 折叠和归约

kotlin
val numbers = listOf(1, 2, 3, 4, 5)

// fold(带初始值)
val sum = numbers.fold(0) { acc, num -> acc + num }  // 15
val product = numbers.fold(1) { acc, num -> acc * num }  // 120

// foldRight(从右到左)
val result = numbers.foldRight("") { num, acc -> "$acc$num" }  // "54321"

// reduce(无初始值,至少一个元素)
val sum2 = numbers.reduce { acc, num -> acc + num }  // 15

// reduceRight
val result2 = numbers.reduceRight { num, acc -> "$acc$num" }  // "54321"

// runningFold(累积过程)
val runningSum = numbers.runningFold(0) { acc, num -> acc + num }
// [0, 1, 3, 6, 10, 15]

// runningReduce
val runningProduct = numbers.runningReduce { acc, num -> acc * num }
// [1, 2, 6, 24, 120]

6.4 组合操作符

kotlin
val list1 = listOf(1, 2, 3)
val list2 = listOf("a", "b", "c")

// zip(组合两个集合)
list1.zip(list2)
// [(1, "a"), (2, "b"), (3, "c")]

list1.zip(list2) { num, str -> "$num$str" }
// ["1a", "2b", "3c"]

// unzip(解压缩)
val pairs = listOf(1 to "a", 2 to "b", 3 to "c")
val (numbers, letters) = pairs.unzip()
// numbers = [1, 2, 3], letters = ["a", "b", "c"]

// 多个集合的 zip
list1.zip(list2).zip(listOf(true, false, true))
// [((1, "a"), true), ((2, "b"), false), ((3, "c"), true)]

6.5 关联操作符

kotlin
val list = listOf("a", "b", "c")

// associate(创建 Map)
list.associate { it to it.uppercase() }
// {"a"="A", "b"="B", "c"="C"}

list.associateWith { it.length }
// {"a"=1, "b"=1, "c"=1}

list.associateBy { it.uppercase() }
// {"A"="a", "B"="b", "C"="c"}

// toMap
list.map { it to it.length }.toMap()
// {"a"=1, "b"=1, "c"=1}

6.6 序列(Sequence)操作

kotlin
// 序列:惰性求值,适合大数据集
val sequence = sequenceOf(1, 2, 3, 4, 5)
    .filter {
        println("Filter: $it")
        it % 2 == 0
    }
    .map {
        println("Map: $it")
        it * 2
    }

// 不会执行任何操作(惰性)

// 终端操作触发计算
val result = sequence.take(2).toList()
// 输出:
// Filter: 1
// Filter: 2
// Map: 2
// Filter: 3
// Filter: 4
// Map: 4

// 与 List 对比
val listResult = listOf(1, 2, 3, 4, 5)
    .filter {
        println("Filter: $it")
        it % 2 == 0
    }
    .map {
        println("Map: $it")
        it * 2
    }
    .take(2)
// 输出:
// Filter: 1
// Filter: 2
// Filter: 3
// Filter: 4
// Filter: 5
// Map: 2
// Map: 4
// (所有元素都处理了,即使只取 2 个)

6.7 Android 常用高阶函数

kotlin
// 1. LiveData/Flow 操作
fun <T> LiveData<T>.observeOnce(owner: LifecycleOwner, observer: Observer<T>) {
    observe(owner, object : Observer<T> {
        override fun onChanged(value: T) {
            observer.onChanged(value)
            removeObserver(this)
        }
    })
}

// 2. View 操作
fun View.doOnLayout(action: (View) -> Unit) {
    if (isLaidOut) {
        action(this)
    } else {
        addOnLayoutChangeListener { view, _, _, _, _, _, _, _, _ ->
            view.removeOnLayoutChangeListener(this)
            action(view)
        }
    }
}

fun View.doOnPreDraw(action: (View) -> Unit) {
    viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
        override fun onPreDraw(): Boolean {
            viewTreeObserver.removeOnPreDrawListener(this)
            action(this@doOnPreDraw)
            return true
        }
    })
}

// 3. 协程作用域
fun CoroutineScope.launchWhenStarted(block: suspend CoroutineScope.() -> Unit): Job {
    return launch {
        lifecycleFlow.filter { it >= Lifecycle.State.STARTED }.collect {
            block()
        }
    }
}

// 4. 结果处理
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Throwable) : Result<Nothing>()
}

fun <T, R> Result<T>.map(transform: (T) -> R): Result<R> {
    return when (this) {
        is Result.Success -> Result.Success(transform(data))
        is Result.Error -> this
    }
}

fun <T> Result<T>.onSuccess(action: (T) -> Unit): Result<T> {
    return when (this) {
        is Result.Success -> {
            action(data)
            this
        }
        is Result.Error -> this
    }
}

fun <T> Result<T>.onError(action: (Throwable) -> Unit): Result<T> {
    return when (this) {
        is Result.Success -> this
        is Result.Error -> {
            action(exception)
            this
        }
    }
}

7. 面试考点汇总

7.1 基础问题

Q1: 什么是高阶函数?举例说明。

kotlin
// 答案要点:
// 1. 接受函数作为参数的函数
// 2. 或返回函数的函数
// 3. 标准库中的 map、filter、forEach 都是高阶函数

// 接受函数参数
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// 返回函数
fun getMultiplier(factor: Int): (Int) -> Int {
    return { x -> x * factor }
}

Q2: Lambda 表达式的语法是什么?

kotlin
// 答案要点:
// 1. { 参数 -> 函数体 }
// 2. 单个参数可以用 it
// 3. 可以放在括号外(尾随 Lambda)
// 4. 类型可以推断

// 完整语法
val sum = { a: Int, b: Int -> a + b }

// 类型推断
val sum: (Int, Int) -> Int = { a, b -> a + b }

// 单个参数
val double: (Int) -> Int = { it * 2 }

// 尾随 Lambda
list.map { it * 2 }

Q3: 函数类型如何声明?

kotlin
// 答案要点:
// 1. (参数类型,...) -> 返回类型
// 2. 可以存储为变量
// 3. 可以作为参数和返回值

val func: (Int, Int) -> Int = { a, b -> a + b }

// 无参数
val greet: () -> String = { "Hello" }

// 无返回值
val print: () -> Unit = { println("Hello") }

// 带接收者
val block: StringBuilder.() -> Unit = { append("Hello") }

7.2 进阶问题

Q4: inline 关键字的作用是什么?

kotlin
// 答案要点:
// 1. 将 Lambda 代码内联到调用处
// 2. 避免 Lambda 对象创建开销
// 3. 支持非局部返回
// 4. 需要 reified 时使用

inline fun <T> List<T>.forEach(action: (T) -> Unit) {
    for (element in this) action(element)
}

// 内联后直接展开
for (element in this) {
    println(element)  // Lambda 内容直接在这里
}

Q5: noinline 和 crossinline 的区别?

kotlin
// 答案要点:
// 1. noinline 禁止特定 Lambda 内联
// 2. crossinline 禁止非局部返回
// 3. noinline 用于将 Lambda 传递给其他函数
// 4. crossinline 用于在另一个 Lambda 中调用

inline fun test(
    inlineParam: () -> Unit,
    noinline noInlineParam: () -> Unit
) {
    inlineParam()  // 内联
    executeLater(noInlineParam)  // 可以作为对象传递
}

inline fun test2(crossinline block: () -> Unit) {
    val runnable = Runnable {
        block()  // 不能 return
    }
}

Q6: reified 泛型是什么?如何使用?

kotlin
// 答案要点:
// 1. 只能在 inline 函数中使用
// 2. 在运行时保留类型信息
// 3. 可以用于 is/as 检查
// 4. 常用于过滤、启动 Activity 等

inline fun <reified T> isInstanceOf(obj: Any): Boolean {
    return obj is T
}

inline fun <reified T> List<*>.filterIsInstance(): List<T> {
    return this.filterIsInstance<T>()
}

inline fun <reified T : Activity> Context.startActivity() {
    val intent = Intent(this, T::class.java)
    startActivity(intent)
}

7.3 原理问题

Q7: 高阶函数的性能开销?

kotlin
// 答案要点:
// 1. Lambda 会创建对象(函数对象)
// 2. 有分配和 GC 开销
// 3. 使用 inline 可以消除开销
// 4. 基本类型参数注意装箱

// 普通高阶函数
list.forEach { println(it) }
// 1. 创建 Lambda 对象
// 2. 调用 forEach 方法
// 3. 在循环中调用 Lambda

// 内联高阶函数
inline fun <T> List<T>.forEach(action: (T) -> Unit)
// 直接展开 Lambda 内容,无对象创建

Q8: 尾随 Lambda 的规则?

kotlin
// 答案要点:
// 1. 最后一个参数是函数时可以放在括号外
// 2. 如果只有 Lambda 参数,括号可以省略
// 3. 提高代码可读性

// 尾随 Lambda
list.map { it * 2 }

// 只有 Lambda 参数
run {
    println("Hello")
}

// 多个参数时
list.fold(0) { acc, num ->
    acc + num
}

7.4 实战问题

Q9: 如何实现一个重试机制的高阶函数?

kotlin
// 答案要点:
// 1. 接受 suspend Lambda 作为参数
// 2. 循环执行直到成功或达到最大次数
// 3. 使用 delay 实现退避
// 4. 抛出最后的异常

suspend fun <T> retry(
    times: Int = 3,
    delayMs: Long = 1000,
    operation: suspend () -> T
): T {
    var lastException: Exception? = null
    
    repeat(times) { attempt ->
        try {
            return operation()
        } catch (e: Exception) {
            lastException = e
            if (attempt < times - 1) {
                delay(delayMs)
            }
        }
    }
    
    throw lastException ?: Exception("Unknown error")
}

// 使用
val result = retry(times = 3, delayMs = 2000) {
    api.loadData()
}

Q10: 如何使用高阶函数实现 DSL?

kotlin
// 答案要点:
// 1. 使用带接收者的 Lambda
// 2. 使用 apply/scope 函数
// 3. 提供清晰的配置 API
// 4. 返回构建的对象

class Dialog {
    var title: String = ""
    var message: String = ""
    var positiveButton: String = "OK"
    
    fun show() {
        println("Dialog: $title - $message")
    }
}

fun dialog(configure: Dialog.() -> Unit): Dialog {
    return Dialog().apply(configure)
}

// 使用
dialog {
    title = "提示"
    message = "确定要删除吗?"
    positiveButton = "删除"
}.show()

Q11: 标准库中有哪些常用的高阶函数?

kotlin
// 答案要点:
// 1. 转换:map、flatMap、mapIndexed
// 2. 过滤:filter、filterNot、filterIndexed
// 3. 取/舍:take、takeWhile、drop、dropWhile
// 4. 查找:find、findLast、indexOfFirst
// 5. 判断:any、all、none、contains
// 6. 折叠:fold、reduce、foldRight
// 7. 分组:groupBy、partition、chunked
// 8. 组合:zip、unzip

val numbers = listOf(1, 2, 3, 4, 5)

numbers.map { it * 2 }           // 转换
numbers.filter { it % 2 == 0 }   // 过滤
numbers.take(3)                  // 取
numbers.find { it > 3 }          // 查找
numbers.any { it > 3 }           // 判断
numbers.fold(0) { a, b -> a + b } // 折叠
numbers.groupBy { it % 2 }       // 分组

最佳实践总结

✅ 推荐做法

kotlin
// 1. 使用标准库高阶函数
list.map { it * 2 }
list.filter { it > 0 }

// 2. 使用尾随 Lambda
list.fold(0) { acc, num ->
    acc + num
}

// 3. 内联高阶函数
inline fun <T> List<T>.forEach(action: (T) -> Unit)

// 4. 使用 reified 泛型
inline fun <reified T> List<*>.filterIsInstance(): List<T>

// 5. 清晰的 Lambda 参数命名
list.map { number -> number * 2 }

❌ 避免做法

kotlin
// 1. 避免过长的 Lambda
list.map {
    // 几十行代码
}

// 2. 避免嵌套过深
list.map { x ->
    list2.map { y ->
        list3.map { z ->
            // ...
        }
    }
}

// 3. 避免不必要的内联
// 不是所有高阶函数都需要 inline

// 4. 避免忽略 Lambda 参数
list.forEach {
    // 不使用 it
}

参考资料


最后更新:2026-04-14