一、take:限制收集的元素数量
功能
仅收集流中前 N 个元素,后续元素会被忽略。
适用场景
- 仅需处理部分数据(如预览前几条数据)。
- 避免处理过时或无用的后续数据。
示例
flowOf(1, 2, 3, 4, 5)
.take(3) // 仅收集前 3 个元素(1, 2, 3)
.collect { println(it) }
// 输出:1 → 2 → 3
二、reduce:累积元素并生成最终结果
功能
将流中的元素依次累积(类似集合的 reduce 操作),最终返回单一结果。
适用场景
- 求和、求积、字符串拼接等累积操作。
- 需要将流数据转换为单一聚合值。
示例
val sum = flowOf(1, 2, 3, 4, 5)
.reduce { acc, value -> acc + value }
println(sum) // 输出:15(1+2+3+4+5)
三、zip:组合两个流的元素
功能
将两个流的元素按顺序一一配对,生成新的组合值。若任一流提前结束,合并结束。
适用场景
- 合并两个相关流的数据(如用户信息 + 订单信息)。
- 需要严格按顺序对齐元素。
示例
val numbers = flowOf(1, 2, 3)
val letters = flowOf("A", "B", "C")
numbers.zip(letters) { num, letter -> "$num$letter" }
.collect { println(it) }
// 输出:1A → 2B → 3C
四、flatMap:扁平化映射流的元素
功能
将每个元素转换为新的流,并将所有生成的流扁平化为单个流。
变体:
- **
flatMapConcat**:按顺序处理(前一个流结束后才开始下一个)。 - **
flatMapMerge**:并发处理多个流(通过concurrency参数控制并发数)。 - **
flatMapLatest**:仅处理最新的映射流,取消前一个未完成的流。
适用场景
- 每个元素需要触发独立的异步操作(如请求详情数据)。
- 需要合并嵌套流的结果。
示例对比
-
**
flatMapConcat(顺序执行)** flowOf(1, 2, 3) .flatMapConcat { value -> flow { emit("A$value") delay(100) emit("B$value") } } .collect { println(it) } // 输出:A1 → B1 → A2 → B2 → A3 → B3 -
**
flatMapMerge(并发执行)** flowOf(1, 2, 3) .flatMapMerge(concurrency = 2) { value -> flow { emit("A$value") delay(100) emit("B$value") } } .collect { println(it) } // 输出顺序可能为:A1 → A2 → B1 → B2 → A3 → B3 -
**
flatMapLatest(仅处理最新)** flowOf(1, 2, 3) .flatMapLatest { value -> flow { emit("Start$value") delay(200) // 若新元素到达,取消此流 emit("End$value") } } .collect { println(it) } // 输出:Start1 → Start2 → Start3 → End3(前两个未完成的任务被取消)
五、操作符对比与选型
| 操作符 | 行为 | 适用场景 | 注意事项 |
|---|---|---|---|
take | 截取前 N 个元素 | 限制处理范围,避免冗余操作 | 不支持负数或动态计算 N |
reduce | 累积计算结果 | 聚合流数据为单一值 | 流必须非空,否则抛出异常 |
zip | 严格按顺序配对元素 | 数据对齐合并 | 任一流结束则合并结束 |
flatMapConcat | 顺序展开嵌套流 | 需要严格按顺序处理子流 | 可能因长耗时任务导致背压 |
flatMapMerge | 并发展开嵌套流 | 提升子流处理效率 | 需合理设置并发数(默认 16) |
flatMapLatest | 仅保留最新子流 | 响应最新数据(如搜索框输入联想) | 需处理子流取消逻辑 |
六、综合实践示例
场景:根据用户输入关键词实时搜索,仅保留最后一次请求结果。
// 模拟用户输入流
val queryFlow = flowOf("K", "Ko", "Kot", "Kotlin")
queryFlow
.debounce(300) // 防抖:300ms 内无新输入才触发
.flatMapLatest { query ->
flow {
emit("Searching: $query")
delay(1000) // 模拟网络请求
emit("Results for: $query")
}
}
.collect { println(it) }
// 输出(假设快速输入):
// Searching: Kotlin → Results for: Kotlin
通过合理组合这些操作符,可以实现复杂的流数据处理逻辑,同时兼顾性能和可维护性