在 Project Reactor(Reactive Streams 的实现库,常用于 Spring WebFlux)中,map
、flatMap
、concatMap
和 flatMapSequential
是常用的操作符,但它们的功能和行为有显著区别。以下是它们的详细对比:
1. 功能对比
操作符 | 功能描述 | 输入类型 | 输出类型 | 顺序性 | 并发性 |
---|---|---|---|---|---|
map | 同步转换元素 | 元素(T ) | 元素(R ) | 保持顺序 | 无并发 |
flatMap | 异步转换元素为 Publisher,并发处理所有 Publisher | 元素(T ) | Publisher(Publisher<R> ) | 不保证顺序 | 并发 |
concatMap | 异步转换元素为 Publisher,按顺序处理 Publisher | 元素(T ) | Publisher(Publisher<R> ) | 保持顺序 | 无并发 |
flatMapSequential | 异步转换元素为 Publisher,并发处理 Publisher,但按顺序发射结果 | 元素(T ) | Publisher(Publisher<R> ) | 保持顺序 | 并发 |
2. 行为对比
map
- 作用:将 Flux 或 Mono 中的每个元素同步转换为另一个元素。
- 特点:
- 同步操作。
- 不改变流的类型(例如,Flux 仍然是 Flux,Mono 仍然是 Mono)。
- 示例:
输出:java">Flux<Integer> flux = Flux.just(1, 2, 3); flux.map(value -> value * 10) .subscribe(System.out::println);
10 20 30
flatMap
- 作用:将 Flux 或 Mono 中的每个元素异步转换为一个 Publisher(如 Flux 或 Mono),并并发处理这些 Publisher。
- 特点:
- 异步操作。
- 改变流的类型(例如,将 Flux 转换为另一个 Flux)。
- 不保证顺序。
- 示例:
输出(可能无序):java">Flux<Integer> flux = Flux.just(1, 2, 3); flux.flatMap(value -> Mono.just(value * 10).delayElement(Duration.ofMillis(100)) // 异步转换 ).subscribe(System.out::println);
10 20 30
concatMap
- 作用:将 Flux 或 Mono 中的每个元素异步转换为一个 Publisher(如 Flux 或 Mono),并按顺序连接这些 Publisher。
- 特点:
- 异步操作。
- 改变流的类型(例如,将 Flux 转换为另一个 Flux)。
- 按顺序处理 Publisher。
- 示例:
输出:java">Flux<Integer> flux = Flux.just(1, 2, 3); flux.concatMap(value -> Mono.just(value * 10).delayElement(Duration.ofMillis(100)) // 异步转换 ).subscribe(System.out::println);
10 20 30
flatMapSequential
- 作用:将 Flux 或 Mono 中的每个元素异步转换为一个 Publisher(如 Flux 或 Mono),并发处理这些 Publisher,但按顺序发射结果。
- 特点:
- 异步操作。
- 改变流的类型(例如,将 Flux 转换为另一个 Flux)。
- 并发处理,但按顺序发射结果。
- 示例:
输出:java">Flux<Integer> flux = Flux.just(1, 2, 3); flux.flatMapSequential(value -> Mono.just(value * 10).delayElement(Duration.ofMillis(100)) // 异步转换 ).subscribe(System.out::println);
10 20 30
3. 适用场景
操作符 | 适用场景 |
---|---|
map | 简单的同步转换操作,例如将字符串转换为大写、将数字乘以某个值等。 |
flatMap | 需要并发处理的异步操作,且不关心顺序,例如并发请求多个外部服务。 |
concatMap | 需要异步操作且保持顺序的场景,例如按顺序插入数据库记录。 |
flatMapSequential | 需要并发处理但结果顺序重要的场景,例如并发请求多个外部服务但按顺序返回结果。 |
4. 性能与资源消耗
操作符 | 性能与资源消耗 |
---|---|
map | 同步操作,性能开销小。 |
flatMap | 异步操作,性能开销较大,适合高并发场景。 |
concatMap | 异步操作,性能开销较大,顺序性可能导致性能瓶颈。 |
flatMapSequential | 异步操作,性能开销较大,适合需要并发处理但结果顺序重要的场景。 |
总结
map
:用于同步的元素转换,适合简单的数据处理。flatMap
:用于异步的元素转换,并发处理所有 Publisher,适合高并发场景。concatMap
:用于异步的元素转换,按顺序处理 Publisher,适合需要顺序性的场景。flatMapSequential
:用于异步的元素转换,并发处理 Publisher 但按顺序发射结果,适合需要并发处理且结果顺序重要的场景。