3.1 Lambda 表达式基础
3.1.1 函数式编程的核心理念
什么是函数式编程?
- 函数是第一等公民(First-class citizen)
- 不可变性(Immutability)
- 纯函数(Pure function)
- 高阶函数(Higher-order function)
为什么需要函数式编程?
kotlin
// 命令式编程 - 关注"怎么做"
fun filterAdults(users: List<User>): List<User> {
val result = mutableListOf<User>()
for (user in users) {
if (user.age >= 18) {
result.add(user)
}
}
return result
}
// 函数式编程 - 关注"做什么"
fun filterAdultsFunctional(users: List<User>): List<User> {
return users.filter { it.age >= 18 }
}
对比分析:
| 方面 | 命令式编程 | 函数式编程 |
|---|---|---|
| 代码量 | 较多 | 较少 |
| 可读性 | 需要理解循环逻辑 | 接近自然语言 |
| 可维护性 | 需要手动管理状态 | 无状态,易于维护 |
| 可测试性 | 需要模拟完整流程 | 纯函数易于测试 |
| 并发安全 | 需要同步机制 | 天然线程安全 |
3.1.2 Lambda 语法
Lambda 表达式的基本语法:
kotlin
// 完整语法
val sum: (Int, Int) -> Int = { a: Int, b: Int -> a + b }
// 简化语法(类型推断)
val sum2 = { a: Int, b: Int -> a + b }
// 单参数(可以省略括号)
val square: (Int) -> Int = { it * it }
// 无参数
val greet: () -> Unit = { println("Hello") }
// 多行 Lambda
val calculate: (Int, Int) -> Pair<Int, Int> = { a, b ->
val sum = a + b
val product = a * b
Pair(sum, product)
}
Lambda 表达式的特性:
kotlin
// 1. 可以赋值给变量
val add = { a: Int, b: Int -> a + b }
println(add(3, 5)) // 输出:8
// 2. 可以作为参数传递
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
val result = calculate(10, 5) { a, b -> a + b } // 输出:15
// 3. 可以作为返回值
fun createAdder(addend: Int): (Int) -> Int {
return { number -> number + addend }
}
val addFive = createAdder(5)
println(addFive(10)) // 输出:15
//上面代码通过工具可以看到
@NotNull
public static final Function1 createAdder(int addend) {
return BookKt::createAdder$lambda$0;
}
//addFive方法
private static final int createAdder$lambda$0(int $addend, int number) {
return number + $addend;
}
3.1.3 尾递归优化
递归的问题:栈溢出风险。
kotlin
// 普通递归 - 栈溢出风险---//3*2*1*1
fun factorial(n: Long): Long {
return if (n == 0L) 1 else n * factorial(n - 1)
}
// factorial(100000) // 栈溢出
尾递归的条件:
- 递归调用是函数的最后一步操作
- 必须使用
tailrec关键字标记 - 不能在 try-catch-finally 块中
实际应用:
kotlin
// 尾递归优化 - 深度优先搜索
tailrec fun findTarget(
list: List<Int>,
target: Int,
index: Int = 0
): Int? {
return when {
index >= list.size -> null
list[index] == target -> index
else -> findTarget(list, target, index + 1)
}
}
val list = (1..100000).toList()
println(findTarget(list, 50000)) // 输出:49999
3.1.4 匿名函数
匿名函数 vs Lambda 表达式:
kotlin
// Lambda 表达式
val lambda1: (Int, Int) -> Int = { a, b -> a + b }
// 匿名函数
val lambda2: (Int, Int) -> Int = fun(a: Int, b: Int): Int {
return a + b
}
// 简化的匿名函数
val lambda3 = fun(a: Int, b: Int): Int = a + b
匿名函数的特性:
kotlin
// 1. 显式返回类型
val lambda4 = fun(a: Int, b: Int): Int {
return a + b
}
// 2. 支持返回值类型推断
val lambda5 = fun(a: Int, b: Int) = a + b
// 3. 非局部返回(return 会退出包含它的函数)
fun example() {
val list = listOf(1, 2, 3, 4, 5)
list.forEach {
if (it == 3) return // 退出 example 函数
println(it)
}
println("这行不会执行")
}
example() // 输出:1 2
// 使用匿名函数避免非局部返回
fun example2() {
val list = listOf(1, 2, 3, 4, 5)
list.forEach(fun(it) {
if (it == 3) return@forEach // 只退出 lambda
println(it)
})
println("这行会执行")
}
example2() // 输出:1 2 4 5 这行会执行
3.2 高阶函数与函数类型
3.2.1 函数类型的定义
函数类型语法:
kotlin
// 基本语法:(参数列表) -> 返回值类型
val sum: (Int, Int) -> Int = { a, b -> a + b }
val greet: () -> Unit = { println("Hello") }
val transform: (String) -> String = { it.uppercase() }
// 无返回值(Unit)
val printInt: (Int) -> Unit = { println(it) }
// 可空函数类型
val nullableFunction: ((Int) -> Int)? = null
// 带接收者的函数类型
val String.lastChar: () -> Char = { this[this.length - 1] }
3.2.2 函数作为参数
高阶函数示例:
kotlin
// 函数作为参数
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
// 使用
val sum = calculate(10, 5) { a, b -> a + b }
val difference = calculate(10, 5) { a, b -> a - b }
val product = calculate(10, 5) { a, b -> a * b }
println(sum) // 输出:15
println(difference) // 输出:5
println(product) // 输出:50
实际应用 - 过滤器:
kotlin
// 高阶函数 - 过滤器
fun <T> filterList(list: List<T>, predicate: (T) -> Boolean): List<T> {
val result = mutableListOf<T>()
for (item in list) {
if (predicate(item)) {
result.add(item)
}
}
return result
}
// 使用
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenNumbers = filterList(numbers) { it % 2 == 0 }
val oddNumbers = filterList(numbers) { it % 2 != 0 }
val greaterThanFive = filterList(numbers) { it > 5 }
println(evenNumbers) // 输出:[2, 4, 6, 8, 10]
println(oddNumbers) // 输出:[1, 3, 5, 7, 9]
println(greaterThanFive) // 输出:[6, 7, 8, 9, 10]
3.2.3 函数作为返回值
函数工厂模式:
kotlin
// 函数作为返回值
fun createOperation(operation: String): (Int, Int) -> Int {
return when (operation) {
"add" -> { a, b -> a + b }
"subtract" -> { a, b -> a - b }
"multiply" -> { a, b -> a * b }
"divide" -> { a, b -> a / b }
else -> { _, _ -> 0 }
}
}
// 使用
val add = createOperation("add")
val subtract = createOperation("subtract")
println(add(10, 5)) // 输出:15
println(subtract(10, 5)) // 输出:5
闭包(Closure):
kotlin
// 闭包 - 函数可以访问外部变量
fun createCounter(start: Int = 0): () -> Int {
var count = start
return { ++count }
}
val counter1 = createCounter()
println(counter1()) // 输出:1
println(counter1()) // 输出:2
println(counter1()) // 输出:3
val counter2 = createCounter(10)
println(counter2()) // 输出:11
println(counter2()) // 输出:12
3.2.4 常用高阶函数
let 函数:
kotlin
// let - 在非空时执行操作
val name: String? = "张三"
name?.let {
println("名字长度:${it.length}") // 输出:名字长度:2
}
// 用于链式调用
val result = "hello"
.let { it.uppercase() }
.let { it.reversed() }
.let { "$it!" }
println(result) // 输出:OLLEH!
also 函数:
kotlin
// also - 执行操作并返回对象本身
val user = User("1", "张三", "zhang@example.com", 25)
.also {
println("创建用户:${it.name}") // 输出:创建用户:张三
}
.also {
it.email = "new_email@example.com"
}
println(user.email) // 输出:new_email@example.com
apply 函数:
kotlin
// apply - 配置对象并返回对象本身
val dialog = AlertDialog.Builder(this)
.apply {
setTitle("提示")
setMessage("确定要删除吗?")
setPositiveButton("确定") { _, _ ->
// 点击确定
}
setNegativeButton("取消", null)
}
.create()
with 函数:
kotlin
// with - 在对象上下文中执行多个操作
val user = User("1", "张三", "zhang@example.com", 25)
with(user) {
println("姓名:$name") // 输出:姓名:张三
println("年龄:$age") // 输出:年龄:25
println("邮箱:$email") // 输出:邮箱:zhang@example.com
}
run 函数:
kotlin
// run - 结合 let 和 with 的功能
val result = "hello".run {
println("原字符串:$this") // 输出:原字符串:hello
uppercase().reversed() // 返回 OLLEH
}
println(result) // 输出:OLLEH
// 用于初始化对象
val user = run {
val id = "1"
val name = "张三"
User(id, name, "$name@example.com", 25)
}
takeIf 和 takeUnless:
kotlin
// takeIf - 满足条件时返回对象,否则返回 null
val number = 10
val evenNumber = number.takeIf { it % 2 == 0 }
val oddNumber = number.takeIf { it % 2 != 0 }
println(evenNumber) // 输出:10
println(oddNumber) // 输出:null
// takeUnless - 不满足条件时返回对象
val validNumber = number.takeUnless { it < 0 }
val invalidNumber = number.takeUnless { it >= 0 }
println(validNumber) // 输出:10
println(invalidNumber) // 输出:null
repeat 函数:
kotlin
// repeat - 重复执行操作
repeat(3) {
println("重复执行第 ${it + 1} 次")
}
// 输出:
// 重复执行第 1 次
// 重复执行第 2 次
// 重复执行第 3 次
3.3 集合操作符实战
3.3.1 基础操作符
map - 转换元素:
kotlin
val numbers = listOf(1, 2, 3, 4, 5)
// 转换为平方
val squares = numbers.map { it * it }
println(squares) // 输出:[1, 4, 9, 16, 25]
// 转换为字符串
val strings = numbers.map { "数字:$it" }
println(strings) // 输出:[数字:1, 数字:2, 数字:3, 数字:4, 数字:5]
// 转换为对象
val users = numbers.map { User(it.toString(), "用户$it", "user$it@example.com", it + 18) }
println(users) // 输出:[User(id=1, name=用户1, ...), ...]
filter - 过滤元素:
kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 过滤偶数
val evenNumbers = numbers.filter { it % 2 == 0 }
println(evenNumbers) // 输出:[2, 4, 6, 8, 10]
// 过滤大于 5 的数
val greaterThanFive = numbers.filter { it > 5 }
println(greaterThanFive) // 输出:[6, 7, 8, 9, 10]
// 过滤非空字符串
val strings = listOf("Hello", null, "World", null, "Kotlin")
val nonNullStrings = strings.filterNotNull()
println(nonNullStrings) // 输出:[Hello, World, Kotlin]
filterNot - 过滤不满足条件的元素:
kotlin
val numbers = listOf(1, 2, 3, 4, 5)
val notEvenNumbers = numbers.filterNot { it % 2 == 0 }
println(notEvenNumbers) // 输出:[1, 3, 5]
3.3.2 聚合操作符
reduce - 归约:
kotlin
val numbers = listOf(1, 2, 3, 4, 5)
// 求和
val sum = numbers.reduce { acc, number -> acc + number }
println(sum) // 输出:15
// 求积
val product = numbers.reduce { acc, number -> acc * number }
println(product) // 输出:120
// 查找最大值
val max = numbers.reduce { acc, number -> if (acc > number) acc else number }
println(max) // 输出:5
fold - 折叠(带初始值的归约):
kotlin
val numbers = listOf(1, 2, 3, 4, 5)
// 求和(初始值为 0)
val sum = numbers.fold(0) { acc, number -> acc + number }
println(sum) // 输出:15
// 拼接字符串(初始值为空字符串)
val result = numbers.fold("") { acc, number -> "$acc$number" }
println(result) // 输出:12345
// 构建字符串(带分隔符)
val formatted = numbers.fold("数字:") { acc, number -> "$acc$number, " }
println(formatted) // 输出:数字:1, 2, 3, 4, 5,
sum, average, max, min:
kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
println(numbers.sum()) // 输出:55
println(numbers.average()) // 输出:5.5
println(numbers.maxOrNull()) // 输出:10
println(numbers.minOrNull()) // 输出:1
count - 计数:
kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 总数
println(numbers.count()) // 输出:10
// 偶数数量
println(numbers.count { it % 2 == 0 }) // 输出:5
// 大于 5 的数量
println(numbers.count { it > 5 }) // 输出:5
3.3.3 查找操作符
find - 查找第一个满足条件的元素:
kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 查找第一个偶数
val firstEven = numbers.find { it % 2 == 0 }
println(firstEven) // 输出:2
// 查找第一个大于 5 的数
val firstGreaterThanFive = numbers.find { it > 5 }
println(firstGreaterThanFive) // 输出:6
findLast - 查找最后一个满足条件的元素:
kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 查找最后一个偶数
val lastEven = numbers.findLast { it % 2 == 0 }
println(lastEven) // 输出:10
first 和 last - 获取第一个/最后一个元素:
kotlin
val numbers = listOf(1, 2, 3, 4, 5)
println(numbers.first()) // 输出:1
println(numbers.last()) // 输出:5
// 带条件的 first
println(numbers.first { it > 3 }) // 输出:4
// 带条件的 last
println(numbers.last { it < 5 }) // 输出:4
any, all, none - 检查元素:
kotlin
val numbers = listOf(1, 2, 3, 4, 5)
// 是否有任何元素满足条件
println(numbers.any { it % 2 == 0 }) // 输出:true
println(numbers.any { it > 10 }) // 输出:false
// 是否所有元素都满足条件
println(numbers.all { it > 0 }) // 输出:true
println(numbers.all { it < 5 }) // 输出:false
// 是否没有元素满足条件
println(numbers.none { it > 10 }) // 输出:true
println(numbers.none { it < 5 }) // 输出:false
3.3.4 分组操作符
groupBy - 分组:
kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 按奇偶分组
val groupedByParity = numbers.groupBy { if (it % 2 == 0) "偶数" else "奇数" }
println(groupedByParity)
// 输出:{奇数=[1, 3, 5, 7, 9], 偶数=[2, 4, 6, 8, 10]}
// 按范围分组
val groupedByRange = numbers.groupBy { when {
it <= 3 -> "小"
it <= 6 -> "中"
else -> "大"
}}
println(groupedByRange)
// 输出:{小=[1, 2, 3], 中=[4, 5, 6], 大=[7, 8, 9, 10]}
partition - 分区:
kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 分为奇数和偶数
val (oddNumbers, evenNumbers) = numbers.partition { it % 2 != 0 }
println(oddNumbers) // 输出:[1, 3, 5, 7, 9]
println(evenNumbers) // 输出:[2, 4, 6, 8, 10]
chunked - 分块:
kotlin
val numbers = (1..10).toList()
// 每三个元素分一组
val chunks = numbers.chunked(3)
println(chunks)
// 输出:[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
// 分块并转换
val sumChunks = numbers.chunked(3) { chunk -> chunk.sum() }
println(sumChunks)
// 输出:[6, 15, 24, 10]
3.3.5 排序操作符
sorted - 排序:
kotlin
val numbers = listOf(5, 2, 8, 1, 9, 3)
// 升序排序
val ascNumbers = numbers.sorted()
println(ascNumbers) // 输出:[1, 2, 3, 5, 8, 9]
// 降序排序
val descNumbers = numbers.sortedDescending()
println(descNumbers) // 输出:[9, 8, 5, 3, 2, 1]
// 按条件排序
val users = listOf(
User("1", "张三", "zhang@example.com", 25),
User("2", "李四", "li@example.com", 30),
User("3", "王五", "wang@example.com", 28)
)
val sortedByAge = users.sortedBy { it.age }
println(sortedByAge.map { it.name }) // 输出:[张三, 王五, 李四]
val sortedByAgeDesc = users.sortedByDescending { it.age }
println(sortedByAgeDesc.map { it.name }) // 输出:[李四, 王五, 张三]
3.3.6 集合转换操作符
flatMap - 扁平映射:
kotlin
val lists = listOf(
listOf(1, 2, 3),
listOf(4, 5, 6),
listOf(7, 8, 9)
)
// 扁平化
val flattened = lists.flatMap { it }
println(flattened) // 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]
// 扁平化并转换
val squares = lists.flatMap { list -> list.map { it * it } }
println(squares) // 输出:[1, 4, 9, 16, 25, 36, 49, 64, 81]
distinct - 去重:
kotlin
val numbers = listOf(1, 2, 2, 3, 3, 3, 4, 5, 5)
val distinctNumbers = numbers.distinct()
println(distinctNumbers) // 输出:[1, 2, 3, 4, 5]
// 按条件去重
val users = listOf(
User("1", "张三", "zhang@example.com", 25),
User("2", "张三", "zhang2@example.com", 30),
User("3", "李四", "li@example.com", 25)
)
val distinctByName = users.distinctBy { it.name }
println(distinctByName.map { it.name }) // 输出:[张三, 李四]
3.3.7 序列(Sequence)与惰性求值
序列的优势:避免中间集合的创建,提高性能。
kotlin
val numbers = (1..1000000).toList()
// 列表操作 - 创建多个中间集合
val result1 = numbers
.filter { it % 2 == 0 } // 创建新集合
.map { it * it } // 创建新集合
.take(10) // 创建新集合
// 序列操作 - 不创建中间集合
val result2 = numbers
.asSequence() // 转换为序列
.filter { it % 2 == 0 } // 惰性求值
.map { it * it } // 惰性求值
.take(10) // 惰性求值
.toList() // 终端操作,触发计算
序列 vs 列表性能对比:
kotlin
// 统计操作次数
var operations = 0
val result1 = (1..100)
.filter { operations++; it % 2 == 0 }
.map { operations++; it * it }
.take(5)
.toList()
println("列表操作次数:$operations") // 输出:列表操作次数:150
operations = 0
val result2 = (1..100)
.asSequence()
.filter { operations++; it % 2 == 0 }
.map { operations++; it * it }
.take(5)
.toList()
println("序列操作次数:$operations") // 输出:序列操作次数:15
核心要点回顾
-
Lambda 表达式
- 函数式编程的核心思想
- Lambda 语法与简化
- 尾递归优化
- 匿名函数与非局部返回
-
高阶函数与函数类型
- 函数作为参数
- 函数作为返回值
- 闭包特性
- 常用高阶函数(let, also, apply, with, run)
-
集合操作符
- 基础操作符(map, filter)
- 聚合操作符(reduce, fold, sum, average)
- 查找操作符(find, first, last, any, all, none)
- 分组操作符(groupBy, partition, chunked)
- 排序操作符(sorted, sortedBy)
- 序列与惰性求值