Kotlin Lambda 表达式详解

目录

  1. [Lambda 基础概念](#Lambda 基础概念)
  2. [Lambda 语法详解](#Lambda 语法详解)
  3. [与 Java 对比](#与 Java 对比)
  4. [Lambda 的使用场景](#Lambda 的使用场景)
  5. 高级特性
  6. 实际应用示例

1. Lambda 基础概念

什么是 Lambda?

Lambda 表达式是一个匿名函数,可以作为值传递、存储和调用。

核心特点:

  • 没有函数名
  • 可以作为参数传递
  • 可以作为返回值
  • 可以赋值给变量

2. Lambda 语法详解

2.1 基本语法

kotlin 复制代码
// 完整语法
{ 参数列表 -> 函数体 }

// 示例
val sum = { a: Int, b: Int -> a + b }

2.2 Lambda 的类型

Lambda 的类型是函数类型 ,格式:(参数类型) -> 返回类型

kotlin 复制代码
// 无参数,无返回值
val action: () -> Unit = { println("Hello") }

// 一个参数,返回 Int
val length: (String) -> Int = { it.length }

// 两个参数,返回 String
val combine: (String, String) -> String = { a, b -> "$a$b" }

// 参数为函数类型(高阶函数)
val higherOrder: ((Int) -> Int) -> Int = { func -> func(5) }

2.3 Lambda 的简化写法

情况1:参数类型可以推断
kotlin 复制代码
// 完整写法
val length1: (String) -> Int = { str: String -> str.length }

// 简化写法(类型推断)
val length2: (String) -> Int = { str -> str.length }
情况2:单个参数可以用 it
kotlin 复制代码
// 完整写法
val length1: (String) -> Int = { str -> str.length }

// 使用 it(最常用)
val length2: (String) -> Int = { it.length }
情况3:最后一个参数是 Lambda,可以移出括号
kotlin 复制代码
// 标准写法
list.filter({ it > 0 })

// Lambda 移出括号(推荐)
list.filter { it > 0 }

// 多个参数的情况
list.fold(0, { acc, value -> acc + value })
list.fold(0) { acc, value -> acc + value }  // 推荐
情况4:Lambda 是唯一参数,可以省略括号
kotlin 复制代码
// 标准写法
list.forEach({ println(it) })

// 省略括号
list.forEach { println(it) }

3. 与 Java 对比

3.1 基本语法对比

特性 Kotlin Java 8+
语法 { x -> x * 2 } x -> x * 2
类型 (Int) -> Int Function<Int, Integer>
单参数简化 it 无(必须写参数名)
调用方式 func(5) func.apply(5)

3.2 实际代码对比

Kotlin:

kotlin 复制代码
val numbers = listOf(1, 2, 3, 4, 5)
val doubled = numbers.map { it * 2 }
val filtered = numbers.filter { it > 3 }
numbers.forEach { println(it) }

Java:

java 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubled = numbers.stream()
    .map(x -> x * 2)
    .collect(Collectors.toList());
List<Integer> filtered = numbers.stream()
    .filter(x -> x > 3)
    .collect(Collectors.toList());
numbers.forEach(x -> System.out.println(x));

4. Lambda 的使用场景

4.1 作为函数参数(高阶函数)

kotlin 复制代码
// 定义高阶函数
fun processNumbers(numbers: List<Int>, operation: (Int) -> Int): List<Int> {
    return numbers.map(operation)
}

// 使用
val numbers = listOf(1, 2, 3, 4, 5)
val doubled = processNumbers(numbers) { it * 2 }
val squared = processNumbers(numbers) { it * it }

4.2 集合操作

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

// map: 转换每个元素
val doubled = numbers.map { it * 2 }

// filter: 过滤元素
val evens = numbers.filter { it % 2 == 0 }

// forEach: 遍历执行
numbers.forEach { println(it) }

// find: 查找第一个满足条件的
val firstEven = numbers.find { it % 2 == 0 }

// any: 判断是否有满足条件的
val hasEven = numbers.any { it % 2 == 0 }

// all: 判断是否全部满足条件
val allPositive = numbers.all { it > 0 }

// count: 统计满足条件的数量
val evenCount = numbers.count { it % 2 == 0 }

// fold: 累积操作
val sum = numbers.fold(0) { acc, value -> acc + value }

// reduce: 累积操作(无初始值)
val product = numbers.reduce { acc, value -> acc * value }

4.3 作用域函数(Scope Functions)

Kotlin 提供了 5 个作用域函数,都使用 Lambda:

let
kotlin 复制代码
// 使用 let 安全调用
val result = nullableString?.let { 
    it.length  // it 是 nullableString
}

// 等价于 Java
// if (nullableString != null) {
//     int result = nullableString.length();
// }
run
kotlin 复制代码
// run 可以访问对象成员
val result = "Hello".run {
    length + uppercase().length  // this 是 "Hello"
}
with
kotlin 复制代码
// with 不是扩展函数
val result = with("Hello") {
    length + uppercase().length  // this 是 "Hello"
}
apply
kotlin 复制代码
// apply 返回对象本身
val person = Person().apply {
    name = "张三"
    age = 25
    // 返回 this(Person 对象)
}
also
kotlin 复制代码
// also 返回对象本身,但用 it 访问
val numbers = mutableListOf(1, 2, 3)
numbers.also { 
    println("列表大小: ${it.size}")  // it 是 numbers
}.add(4)

4.4 延迟初始化

kotlin 复制代码
// lazy 初始化
val expensiveValue: String by lazy {
    println("计算中...")
    "计算结果"
}

// 第一次访问时才计算
println(expensiveValue)  // 输出: 计算中... 计算结果
println(expensiveValue)  // 输出: 计算结果(不再计算)

5. 高级特性

5.1 带接收者的 Lambda(Receiver)

kotlin 复制代码
// 定义带接收者的函数类型
fun buildString(builder: StringBuilder.() -> Unit): String {
    val sb = StringBuilder()
    sb.builder()  // 在 StringBuilder 上下文中执行
    return sb.toString()
}

// 使用
val result = buildString {
    append("Hello")
    append(" ")
    append("World")
    // this 是 StringBuilder 实例
}

5.2 Lambda 中的 return

kotlin 复制代码
// 普通 return(从函数返回)
fun findFirst(numbers: List<Int>): Int? {
    numbers.forEach {
        if (it > 5) {
            return null  // 从 findFirst 函数返回
        }
    }
    return 0
}

// 标签 return(从 Lambda 返回)
fun findFirstLabeled(numbers: List<Int>): Int? {
    numbers.forEach label@{
        if (it > 5) {
            return@label  // 只从 Lambda 返回,继续循环
        }
    }
    return 0
}

// 隐式标签(使用函数名)
fun findFirstImplicit(numbers: List<Int>): Int? {
    numbers.forEach {
        if (it > 5) {
            return@forEach  // 从 forEach 的 Lambda 返回
        }
    }
    return 0
}

5.3 Lambda 参数解构

kotlin 复制代码
// Map 遍历
val map = mapOf("a" to 1, "b" to 2, "c" to 3)
map.forEach { (key, value) ->
    println("$key -> $value")
}

// List 中的 Pair
val pairs = listOf(Pair("a", 1), Pair("b", 2))
pairs.forEach { (first, second) ->
    println("$first -> $second")
}

5.4 多个 Lambda 参数

kotlin 复制代码
// 定义
fun process(
    onStart: () -> Unit,
    onProgress: (Int) -> Unit,
    onComplete: (String) -> Unit
) {
    onStart()
    for (i in 1..10) {
        onProgress(i)
    }
    onComplete("完成")
}

// 使用(最后一个 Lambda 可以移出括号)
process(
    onStart = { println("开始") },
    onProgress = { println("进度: $it") }
) { result ->
    println("结果: $result")
}

6. 实际应用示例

6.1 Android/Compose 中的使用

kotlin 复制代码
// Button 点击事件
Button(onClick = { 
    println("按钮被点击")
}) {
    Text("点击我")
}

// 列表项点击
LazyColumn {
    items(items) { item ->
        Card(
            onClick = { handleItemClick(item) }
        ) {
            Text(item.name)
        }
    }
}

// 状态管理
var count by remember { mutableStateOf(0) }
Button(onClick = { count++ }) {
    Text("计数: $count")
}

6.2 网络请求回调

kotlin 复制代码
// 定义回调接口
fun fetchData(
    onSuccess: (String) -> Unit,
    onError: (Exception) -> Unit
) {
    // 模拟网络请求
    try {
        val data = "数据内容"
        onSuccess(data)
    } catch (e: Exception) {
        onError(e)
    }
}

// 使用
fetchData(
    onSuccess = { data ->
        println("成功: $data")
    },
    onError = { error ->
        println("错误: ${error.message}")
    }
)

6.3 自定义 DSL(领域特定语言)

kotlin 复制代码
// 定义 DSL 构建器
class HTML {
    fun body(init: Body.() -> Unit) {
        val body = Body()
        body.init()
    }
}

class Body {
    fun div(init: Div.() -> Unit) {
        val div = Div()
        div.init()
    }
}

class Div {
    var text: String = ""
}

// 使用 DSL
val html = HTML()
html.body {
    div {
        text = "Hello World"
    }
}

7. 最佳实践

7.1 何时使用 Lambda

适合使用:

  • 简单的单行操作
  • 作为高阶函数的参数
  • 集合操作
  • 回调函数

不适合使用:

  • 复杂的多行逻辑(应该提取为函数)
  • 需要多个 return 的复杂逻辑
  • 需要命名和复用的逻辑

7.2 性能考虑

kotlin 复制代码
// ❌ 不好的做法:在循环中创建大量 Lambda
for (i in 1..1000000) {
    list.map { it * i }  // 每次循环都创建 Lambda
}

// ✅ 好的做法:提取 Lambda
val multiplier = { x: Int -> x * 2 }
for (i in 1..1000000) {
    list.map(multiplier)
}

7.3 可读性

kotlin 复制代码
// ❌ 可读性差:嵌套太深
list.filter { it > 0 }
    .map { it * 2 }
    .filter { it < 100 }
    .forEach { println(it) }

// ✅ 可读性好:提取中间变量
val positiveNumbers = list.filter { it > 0 }
val doubled = positiveNumbers.map { it * 2 }
val filtered = doubled.filter { it < 100 }
filtered.forEach { println(it) }

总结

Kotlin Lambda 的核心优势:

  1. 语法简洁:比 Java 更直观
  2. 类型推断:减少样板代码
  3. 函数式编程:支持高阶函数
  4. 作用域函数:提供强大的对象操作能力
  5. DSL 支持:可以创建领域特定语言

作为 Java 开发者,理解 Lambda 是掌握 Kotlin 函数式编程的关键!

相关推荐
最后一个bug2 小时前
浅显易懂的讲解MMU是如何使用4级页表把虚拟地址转化为物理地址的~
linux·服务器·开发语言·系统架构·计算机外设
superman超哥2 小时前
Rust 函数定义与参数传递:所有权系统下的设计艺术
开发语言·rust·设计艺术·rust函数定义·rust参数传递
2301_789015622 小时前
C++:set/multiset和map/multimap文档详细解析
c语言·开发语言·c++·vscode·排序算法·set·map
“抚琴”的人2 小时前
C#上位机策略模式
开发语言·c#·策略模式
CoderCodingNo2 小时前
【GESP】C++五级真题(数论-素数思想考点) luogu-P10720 [GESP202406 五级] 小杨的幸运数字
开发语言·c++·算法
zmzb01032 小时前
C++课后习题训练记录Day59
开发语言·c++
黎雁·泠崖2 小时前
C 语言文件操作进阶:格式化读写 + 二进制读写 + 随机读写进阶全解
c语言·开发语言
talenteddriver2 小时前
web: jwt令牌构成、创建的基本流程及原理
java·开发语言·python·网络协议·web
这周也會开心2 小时前
双栈实现队列以及双队列实现栈
java·开发语言