Kotlin 从入门到进阶 之Lambda & 集合高阶模块(四)

Kotlin Lambda & 集合高阶模块

1. Lambda 表达式

基础语法

kotlin 复制代码
// 完整 Lambda:参数 -> 返回值
val sum: (Int, Int) -> Int = { a, b -> a + b }
sum(3, 4)  // 7

// 单参数隐式 it
val double: (Int) -> Int = { it * 2 }
double(5)  // 10

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

// 返回 Unit
val printMsg: (String) -> Unit = { msg -> println(msg) }

匿名函数

kotlin 复制代码
// 匿名函数:完整形式,有 return
val abs = fun(x: Int): Int {
    return if (x >= 0) x else -x
}

// 匿名函数作为参数
fun execute(action: () -> Unit) {
    action()
}

execute(fun() { println("匿名函数") })

简化写法优先级

kotlin 复制代码
// 规则一:单参数 Lambda,可用 it 替代参数名
listOf(1, 2, 3).map { it * 2 }

// 规则二:最后一个参数是 Lambda,可移到括号外
listOf(1, 2, 3).map({ it * 2 })    // 标准
listOf(1, 2, 3).map { it * 2 }     // 简化

// 规则三:唯一参数时,括号可省略
listOf(1, 2, 3).map { it * 2 }

// 多参数时:最后一个是 Lambda 才能外移
reduce { acc, item -> acc + item }  // 正确

Lambda 返回值

kotlin 复制代码
// Lambda 最后一行是返回值(隐式 return)
val len = { str: String -> str.length }
len("Kotlin")  // 6

// 完整显式 return(用于嵌套 Lambda)
val weird = { x: Int ->
    if (x > 0) return@weird x
    -x
}
weird(-5)  // 5

2. 集合框架

可变 vs 不可变

kotlin 复制代码
// 不可变集合:创建后不可修改
val list: List<Int> = listOf(1, 2, 3)
// list.add(4)  // 编译错误

// 可变集合
val mutable: MutableList<Int> = mutableListOf(1, 2, 3)
mutable.add(4)  // OK

// 相互转换
val toMutable = list.toMutableList()
val toFixed = mutable.toList()

List

kotlin 复制代码
// 不可变 List
val names = listOf("Alice", "Bob", "Charlie")

// 可变 List
val users = mutableListOf("Alice", "Bob")
users.add("Charlie")
users.removeAt(0)

// List 操作
names.first()            // "Alice"
names.last()             // "Charlie"
names.getOrNull(10)      // null(安全越界)
names.getOrElse(10) { "Unknown" }  // "Unknown"
names.subList(0, 2)       // ["Alice", "Bob"]

Set

kotlin 复制代码
// 不可变 Set(自动去重)
val colors = setOf("Red", "Green", "Blue", "Red")  // ["Red", "Green", "Blue"]

// 可变 Set
val roles = mutableSetOf("Admin", "User")
roles.add("Guest")
roles.remove("User")

// 集合运算
val a = setOf(1, 2, 3, 4)
val b = setOf(3, 4, 5, 6)

a intersect b     // {3, 4}(交集)
a union b         // {1, 2, 3, 4, 5, 6}(并集)
a subtract b      // {1, 2}(差集)

Map

kotlin 复制代码
// 不可变 Map
val scores = mapOf("Alice" to 90, "Bob" to 85, "Charlie" to 92)

// 可变 Map
val config = mutableMapOf("theme" to "dark")
config["lang"] = "en"
config.remove("theme")

// 读取
scores["Alice"]            // 90(不存在返回 null)
scores.getOrDefault("Tom", 0)  // 0

// 遍历
for ((key, value) in scores) {
    println("$key -> $value")
}

scores.forEach { (k, v) -> println("$k: $v") }

3. 集合高阶算子

map(转换)

kotlin 复制代码
// map:对每个元素执行变换,返回新 List
val numbers = listOf(1, 2, 3, 4, 5)

numbers.map { it * 2 }              // [2, 4, 6, 8, 10]
numbers.map { "数字: $it" }          // ["数字: 1", "数字: 2", ...]

// mapIndexed:带索引变换
numbers.mapIndexed { index, value ->
    "Index $index: $value"
}  // ["Index 0: 1", "Index 1: 2", ...]

filter(过滤)

kotlin 复制代码
numbers.filter { it > 3 }            // [4, 5]
numbers.filterNot { it > 3 }         // [1, 2, 3]

// filterIndexed
numbers.filterIndexed { index, value ->
    index > 0 && value > 2
}  // [3, 4, 5]

// 结合使用
numbers.map { it * 2 }.filter { it > 5 }  // [6, 8, 10]

forEach / onEach

kotlin 复制代码
// forEach:遍历(无返回值 Unit)
listOf(1, 2, 3).forEach { print(it) }  // 123

// onEach:遍历同时返回原集合(用于链式操作)
listOf(1, 2, 3)
    .onEach { println("Processing: $it") }
    .map { it * 2 }  // [2, 4, 6],同时打印 "Processing: 1/2/3"

find / first / last

kotlin 复制代码
// find:返回第一个匹配元素,或 null
val nums = listOf(3, 1, 4, 1, 5, 9)
nums.find { it > 3 }      // 4
nums.find { it > 100 }   // null

// first:第一个元素(越界抛异常)
nums.first()              // 3
nums.first { it > 3 }     // 4

// last:最后一个元素
nums.last()               // 9
nums.last { it < 5 }      // 4

// firstOrNull / lastOrNull(安全版)
nums.firstOrNull { it > 100 }  // null

flatten / flatMap(扁平化)

kotlin 复制代码
// flatten:展平嵌套集合
val nested = listOf(
    listOf(1, 2),
    listOf(3, 4),
    listOf(5)
)
nested.flatten()  // [1, 2, 3, 4, 5]

// flatMap:先 map 再 flatten
val words = listOf("Hello", "World")
words.flatMap { it.toList() }  // [H, e, l, l, o, W, o, r, l, d]

// 实际场景:获取用户的所有角色
users.flatMap { it.roles }  // 所有用户的角色集合

take / drop(截取)

kotlin 复制代码
numbers.take(3)     // [1, 2, 3](取前 3)
numbers.drop(3)     // [4, 5](去除前 3)

numbers.takeLast(2) // [4, 5](取后 2)
numbers.dropLast(2) // [1, 2, 3](去除后 2)

// chunked:分块
numbers.chunked(2)  // [[1, 2], [3, 4], [5]]
numbers.chunked(2) { it.sum() }  // [3, 7, 5]

distinct / sorted

kotlin 复制代码
listOf(1, 2, 2, 3, 1, 3).distinct()  // [1, 2, 3]

listOf(3, 1, 4, 1, 5, 9).sorted()    // [1, 1, 3, 4, 5, 9]
listOf(3, 1, 4, 1, 5, 9).sortedDescending()  // [9, 5, 4, 3, 1, 1]

// sortBy / sortedBy(自定义排序)
listOf("bb", "a", "ccc").sortedBy { it.length }  // [a, bb, ccc]
listOf("bb", "a", "ccc").sortedByDescending { it.length }  // [ccc, bb, a]

groupBy / partition

kotlin 复制代码
// groupBy:按条件分组
val names = listOf("Alice", "Bob", "Anna", "Brian")
names.groupBy { it.first() }  // {A=[Alice, Anna], B=[Bob, Brian]}

// partition:按条件分为两部分
numbers.partition { it > 3 }  // Pair([4, 5], [1, 2, 3])
val (pass, fail) = numbers.partition { it >= 3 }

associate(转换为 Map)

kotlin 复制代码
// associate:元素转 Pair 形成 Map
listOf("Alice", "Bob", "Charlie")
    .associate { it to it.length }  // {Alice=5, Bob=3, Charlie=7}

// associateBy:只用 key 生成 Map
listOf("Alice", "Bob", "Charlie")
    .associateBy { it.first() }  // {A=Alice, B=Bob, C=Charlie}

// associateWith:只用 value 生成 Map
listOf("Alice", "Bob", "Charlie")
    .associateWith { it.length }  // {Alice=5, Bob=3, Charlie=7}

4. 聚合算子 reduce / fold

kotlin 复制代码
// reduce:累积运算(无初始值,第一项作起点)
listOf(1, 2, 3, 4, 5).reduce { acc, item ->
    acc + item
}  // 15(1+2+3+4+5)

listOf(1, 2, 3, 4, 5).reduce { acc, item ->
    acc * item
}  // 120(1*2*3*4*5)

// ⚠️ 空集合 reduce 会抛异常
// listOf<Int>().reduce { acc, item -> acc + item }  // 异常

// fold:有初始值,从初始值开始累积
listOf(1, 2, 3, 4, 5).fold(10) { acc, item ->
    acc + item
}  // 25(10+1+2+3+4+5)

// fold 用于字符串拼接
listOf("a", "b", "c").fold("Start:") { acc, s -> "$acc$s" }  // "Start:abc"

// sumOf:数值求和(更简洁)
listOf(1, 2, 3, 4, 5).sumOf { it * 2 }  // 30

其他聚合算子

kotlin 复制代码
// count:计数
numbers.count { it > 3 }      // 2

// sum / average
numbers.sum()                // 15
numbers.average()            // 3.0

// min / max
numbers.min()               // 1
numbers.max()               // 5
numbers.minByOrNull { -it }  // 5(取最大值的元素)
numbers.maxByOrNull { -it }  // 1(取最小值的元素)

// any / all / none(全称量词)
numbers.any { it > 3 }      // true(任意匹配)
numbers.all { it > 0 }      // true(全部匹配)
numbers.none { it < 0 }     // true(无匹配)

5. 序列 sequence 懒求值

集合 vs 序列

kotlin 复制代码
// 集合:每一步立即求值(急求值)
listOf(1, 2, 3, 4, 5)
    .map { it * 2 }        // [2, 4, 6, 8, 10](立即计算)
    .filter { it > 5 }     // [6, 8, 10](立即计算)
    .take(2)              // [6, 8](立即计算)

// 序列:懒求值(按需计算),链中每个操作不会立即执行
listOf(1, 2, 3, 4, 5)
    .asSequence()
    .map { it * 2 }        // 不立即计算
    .filter { it > 5 }     // 不立即计算
    .take(2)               // 不立即计算
    .toList()              // 这里才真正执行:[6, 8]

性能对比:大数据量

kotlin 复制代码
import kotlin.system.measureTimeMillis

val bigList = (1..1_000_000).toList()

// 急求值:每步都遍历整个集合
val time1 = measureTimeMillis {
    bigList
        .map { it * 2 }
        .filter { it > 1000 }
        .take(10)
        .toList()
}
println("Eager: $time1 ms")  // 约 100+ ms

// 懒求值:只处理必需的元素
val time2 = measureTimeMillis {
    bigList
        .asSequence()
        .map { it * 2 }
        .filter { it > 1000 }
        .take(10)
        .toList()
}
println("Lazy: $time2 ms")  // 约 1-5 ms

序列操作符

kotlin 复制代码
// asSequence():集合转序列
listOf(1, 2, 3).asSequence()

// generateSequence:生成无限序列
val naturals = generateSequence(1) { it + 1 }
naturals.take(5).toList()  // [1, 2, 3, 4, 5]

// 斐波那契数列
val fibonacci = generateSequence(Pair(0, 1)) {
    Pair(it.second, it.first + it.second)
}.map { it.first }

fibonacci.take(10).toList()  // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

// sequenceOf:手动创建序列
val seq = sequenceOf(1, 2, 3, 4, 5)

何时用序列

kotlin 复制代码
// 场景一:大数据量 + 截断操作(take/drop/first)
(1..10_000_000)
    .asSequence()
    .map { it * 2 }
    .filter { it % 1000 == 0 }
    .take(100)
    .toList()

// 场景二:链式操作且中间不产生新集合
// 序列避免创建中间集合(map/filter 各自产生中间 List)

// 注意:元素少时序列额外开销可能更大,简单场景用集合即可
listOf(1, 2, 3).map { it * 2 }  // 小数据量直接用集合

6. 综合实战示例

kotlin 复制代码
// 场景:Android 中获取活跃用户列表
data class User(val name: String, val age: Int, val isActive: Boolean)

// 过滤 -> 转换 -> 排序 -> 取前 10
val activeUsers = users
    .filter { it.isActive }
    .map { "${it.name} (${it.age})" }
    .sortedBy { it }
    .take(10)

// 场景:分组统计
val grouped = products
    .groupBy { it.category }
    .mapValues { (_, items) -> items.sumOf { it.price } }

// 场景:多层嵌套扁平化
orders
    .flatMap { order ->
        order.items.map { item ->
            "${order.customer} -> ${item.name}"
        }
    }

// 场景:序列处理大数据
(1..10_000_000L)
    .asSequence()
    .filter { it % 2 == 0L }
    .map { it * it }
    .take(1000)
    .reduce { acc, l -> acc + l }

快速对照表

算子 作用 返回类型
map 转换每个元素 List<R>
filter 过滤元素 List<T>
forEach 遍历(无返回) Unit
onEach 遍历(返回原集合) List<T>
find 找第一个匹配 T?
first 第一个/匹配元素 T
flatten 展平嵌套集合 List<T>
flatMap 转换+展平 List<R>
reduce 累积(无初始值) T
fold 累积(有初始值) R
take 取前 N 项 List<T>
drop 去除前 N 项 List<T>
groupBy 按条件分组 Map<K, List<V>>
partition 分为两部分 Pair<List, List>
distinct 去重 List<T>
sortedBy 自定义排序 List<T>
asSequence 转懒序列 Sequence<T>

性能口诀

  • 小数据随便用,大数据加 asSequence()
  • 链式截断(take/drop/first)优先考虑序列
  • 避免在 map/filter 中执行重操作(序列可延迟发现问题)
相关推荐
yingjie1101 小时前
用mcc编译的MATLAB EXE被反编译了?这个工具能帮你加固
开发语言·matlab
Evand J1 小时前
【MATLAB绘图】三维曲面与二维映射组合图绘制,进阶教程与代码示例
开发语言·matlab·绘图
农业工作者1 小时前
IDEA解决springboot工程中Cannot resolve symbol ‘SpringApplication异常 maven解决
java·开发语言·maven
上海合宙LuatOS2 小时前
Air780EPM通过MQTT上传温湿度数据
开发语言·人工智能·物联网·junit·luatos
叼烟扛炮3 小时前
C++ 知识点08 类与对象
开发语言·c++·算法·类和对象
你不是我我10 小时前
【Java 开发日记】HTTP3 性能更好,为什么内网微服务依然多用 HTTP2?HTTP2 内网优势是什么?
java·开发语言·微服务
tjl521314_2110 小时前
04C++ 名称空间(Namespace)
开发语言·c++
赏金术士10 小时前
Kotlin 数据流与单双向绑定
android·开发语言·kotlin
逻辑驱动的ken11 小时前
Java高频面试场景题25
java·开发语言·深度学习·面试·职场和发展