附录 A:Reactor/RxJava 操作符速查

按 Reactor 3.8.8 与 RxJava 3.1.12 的实际 API 核对过的操作符速查表:涵盖创建、变换、组合、错误处理、背压控制与实用工具六大类,标注了两库并不对等的操作符(如 first、mergeOrdered、throttleFirst)和已废弃的重载,避免把「名字像」当成「语义相同」。

速查表使用说明

本附录按「先分类、后对照」组织。每个操作符包含:Reactor API、RxJava API(如有)、语义一句话、典型场景。标注了差异点(⚠️)的操作符需特别注意。

一、创建操作符

创建操作符负责从零产生数据流。它们是所有响应式链的起点。

从已有数据创建

ReactorRxJava签名语义
Flux.just(T...)Observable.just(T...)just(T... values)发射固定值序列后完成
Flux.fromIterable(Iterable)Observable.fromIterablefromIterable(Iterable<T>)遍历集合并逐个发射
Flux.fromStream(Stream)Observable.fromStreamfromStream(Stream<T>)遍历 Stream
Flux.range(int, int)Observable.rangerange(int start, int count)发射整数范围
Flux.empty()Observable.empty()empty()立即完成,不发射元素
Flux.never()Observable.never()never()永不终止
Flux.error(Throwable)Observable.error()error(Throwable)立即报错

从异步源创建

ReactorRxJava签名语义
Mono.fromCallableSingle.fromCallablefromCallable(Callable<T>)每次订阅时调用
Mono.fromFutureSingle.fromFuturefromFuture(Future<T>)从 Future 创建
Mono.fromSupplierSingle.fromSupplierfromSupplier(Supplier<T>)每次订阅时生成
Mono.deferSingle.deferdefer(Supplier<Mono<T>>)延迟创建整个流
Mono.createSingle.createcreate(MonoSink<T>)异步创建单值
Flux.createObservable.createcreate(FluxSink<T>)异步创建多值
Flux.generateObservable.generategenerate(Consumer<SynchronousSink<T>>)同步状态机生成

定时创建

ReactorRxJava签名语义
Flux.intervalObservable.intervalinterval(Duration)按固定间隔发射递增计数
Mono.delaySingle.timerdelay(Duration)延迟后发射 0

典型场景

  • HTTP 请求结果:Mono.fromCallable(() -> httpClient.get(url))
  • 轮询数据库:Flux.interval(Duration.ofSeconds(5)).flatMap(i -> queryDB())
  • 初始化配置:Mono.defer(() -> configService.load())

二、变换操作符

变换操作符把一个流转换成另一个流,是业务逻辑的核心载体。

一对一变换

ReactorRxJava签名语义
mapmapmap(Function<T,R>)同步一对一变换
castcastcast(Class<R>)类型转换
ofTypeofTypeofType(Class<R>)过滤+类型转换
index—index()带索引发射 (Long, T);RxJava 无此操作符

一对多展开

ReactorRxJava签名语义
flatMapflatMapflatMap(Function<T,Publisher<R>>)异步展开,无序
concatMapconcatMapconcatMap(Function<T,Publisher<R>>)异步展开,有序
switchMapswitchMapswitchMap(Function<T,Publisher<R>>)只保留最新子流
flatMapSequential—同上无序展开、有序合并

过滤

ReactorRxJava签名语义
filterfilterfilter(Predicate<T>)保留符合条件的
take(long)take(long)take(long n)取前 N 个
takeWhiletakeWhiletakeWhile(Predicate<T>)条件为 true 时取
takeUntiltakeUntiltakeUntil(Predicate<T>)条件为 true 时停止
skip(long)skip(long)skip(long n)跳过前 N 个
skipWhileskipWhileskipWhile(Predicate<T>)条件为 true 时跳过
distinctdistinctdistinct()去重
distinctUntilChangeddistinctUntilChanged同上去除连续重复

分组与窗口

ReactorRxJava签名语义
groupBygroupBygroupBy(Function<T,K>)按键分组
windowwindowwindow(int size)按数量分窗口
bufferbufferbuffer(int size)按数量缓冲为 List

⚠️ 差异点

特性ReactorRxJava
flatMap 默认并发度256Integer.MAX_VALUE
concatMap 默认预取1(FluxConcatMapNoPrefetch,根本不预取)2
switchMap 取消旧流是是

典型场景

  • 列表查询展开:flatMap(page -> queryPage(page))
  • 去重:distinctUntilChanged() 用于去除连续重复的价格推送
  • 分页:buffer(100) 把流转换成每页 100 条的 List

三、组合操作符

组合操作符把多个流合并成一个。

配对组合

ReactorRxJava签名语义
zipzipzip(Publisher... sources)等所有流各一个元素后组合
zipWithzipWithzipWith(Publisher<B>)二元 zip

合并

ReactorRxJava签名语义
mergemergemerge(Publisher... sources)交错,先 emit 先赢
Flux.mergeOrdered(...)—mergeOrdered(Comparator, Publisher...)静态方法;交错合并后按比较器排序
concatconcatconcat(Publisher... sources)顺序连接
combineLatestcombineLatestcombineLatest(Publisher...)最新值组合

选择

ReactorRxJava签名语义
Flux.firstWithSignal(...)Observable.ambArray(...)firstWithSignal(Publisher...)静态方法;取最先发出任意信号(onNext/onError/onComplete)的源
Flux.first(...)(已废弃)Observable.ambArray(...)first(Publisher...)3.8 中标记 @Deprecated,等价于 firstWithSignal,不要在新代码里使用

⚠️ 差异点

  • first / firstWithSignal 是静态工厂,不是实例操作符。它们接受多个 Publisher,语义是“竞争源中谁先发信号就选谁”,对应 RxJava 的 ambArray。
  • RxJava 的 firstElement() 不是对应物。它只处理一条流,返回 Maybe<T>(第一个元素),不能用来在多个源之间竞争。
  • Reactor zip 对空流的处理:如果任一源流为空,结果为空。
  • RxJava combineLatest 初始不发射,直到所有源至少有一个元素。

典型场景

  • 多字段校验:zip(nameValid, emailValid, phoneValid, (a,b,c) -> a && b && c)
  • 行情汇总:combineLatest(priceStream, volumeStream, (p,v) -> new Quote(p,v))

四、错误处理操作符

ReactorRxJava签名语义
onErrorReturnonErrorReturnonErrorReturn(T fallback)替换为默认值;没有 onErrorReturnItem 这个名字
onErrorResumeonErrorResumeNextonErrorResume(Function<Throwable,Publisher<T>>)切换备用流
onErrorMap—onErrorMap(Function<Throwable,Throwable>)转换异常类型
onErrorContinue—onErrorContinue(BiConsumer)⚠️ 跳过错误元素,非标准
retryretryretry(long numRetries)重试 N 次
retryWhenretryWhenretryWhen(Retry)条件重试;3.8 只有 Retry 重载,没有 Function 重载
timeouttimeouttimeout(Duration) / timeout(long, TimeUnit)元素间隔超时

⚠️ 陷阱

  • onErrorContinue 不是 RS 标准,只存在于 Reactor。它会跳过错误元素继续流,可能掩盖问题。
  • Reactor 没有 onErrorReturnItem。把 onErrorReturn 写成不存在的名字,编译期就会失败;需要“出错时给默认值”就用 onErrorReturn(T)。
  • Mono.onErrorReturn 只有三个重载:(T)、(Class<? extends Throwable>, T)、(Predicate<? super Throwable>, T)。没有 Function<Throwable, T> 重载;要根据异常计算返回值,用 onErrorResume(e -> Mono.just(f(e)))。
  • retry 是「重新订阅」不是「重试当前元素」,整个流从头开始。

五、背压控制操作符

ReactorRxJava Flowable签名语义
onBackpressureBufferonBackpressureBufferonBackpressureBuffer()缓冲
onBackpressureBuffer(int)同上onBackpressureBuffer(int maxSize)有界缓冲
onBackpressureDroponBackpressureDroponBackpressureDrop()丢弃溢出
onBackpressureLatestonBackpressureLatestonBackpressureLatest()保留最新
onBackpressureError—onBackpressureError()报错终止(RxJava 无此方法)
limitRate—limitRate(int prefetch)批量 request(RxJava 无)
limitRequest—limitRequest(long)限制上游总请求量(RxJava 无)

⚠️ 背压操作符的三个坑

  1. 两参数 onBackpressureBuffer(int, Consumer) 不是“溢出即丢弃”。第二个参数只是溢出回调,默认策略仍是 BufferOverflowStrategy.ERROR,缓冲区满后流会以 OverflowException 终止。要丢弃并继续,必须用三参数重载显式指定 DROP_LATEST 或 DROP_OLDEST。
  2. 这些操作符会向上游请求 Long.MAX_VALUE。它们不是把背压传回上游,而是在中间接管需求;把它接在 Flux.range 这类本来支持背压的源后面,会把源变成“推”模型。
  3. onBackpressureLatest() 的丢弃要走 doOnDiscard 统计,它没有溢出回调参数。

Reactor 独有

Reactor语义
onBackpressureBuffer(int, BufferOverflowStrategy)有界缓冲 + 溢出策略
onBackpressureBuffer(int, Consumer, BufferOverflowStrategy)有界缓冲 + 溢出回调 + 策略

六、实用工具操作符

副作用(调试与监控)

ReactorRxJava触发时机
doOnNextdoOnNext每个 onNext
doOnErrordoOnErroronError
doOnCompletedoOnCompleteonComplete
doOnCancelFlowable.doOnCancel / Observable.doOnDispose取消
doOnSubscribedoOnSubscribeonSubscribe
doOnRequest—request
doOnTerminatedoOnTerminateonError 或 onComplete
doAfterTerminatedoAfterTerminate终止之后

流量控制

ReactorRxJava语义
delayElements—每个元素延迟
delaySequence—序列整体延迟
samplesample按时间采样
—throttleFirst时间窗口内取第一个;Reactor 没有 throttleFirst
—throttleLatest时间窗口内取最新;Reactor 没有 throttleLatest

日志与调试

ReactorRxJava语义
log()—自动打印所有信号
checkpoint()—检查点追踪
metrics()—Micrometer 指标

操作符选型速查

需求ReactorRxJava
同步变换mapmap
并发 HTTP 请求flatMapflatMap
有序数据库查询concatMapconcatMap
取最新请求结果switchMapswitchMap
合并两个 REST 结果zipzip
实时行情合并combineLatestcombineLatest
失败重试 3 次retry(3)retry(3)
指数退避重试Retry.backoff()retryWhen 手写
3 秒超时timeout(Duration.ofSeconds(3))timeout
缓冲到内存onBackpressureBufferonBackpressureBuffer
允许丢数据onBackpressureDroponBackpressureDrop
只保留最新onBackpressureLatestonBackpressureLatest

常见陷阱速查

操作符陷阱解决方案
flatMap默认并发 256,可能压垮下游指定 flatMap(func, concurrency)
concatMap串行吞吐量低确认是否需要顺序,否则用 flatMap
retry无限重试雪崩始终限制重试次数
timeout不中断阻塞操作配合 subscribeOn(boundedElastic())
onBackpressureBuffer无界 OOM指定上限和溢出策略
cache()永远缓存,内存增长用 replay().limit() 替代
distinct需要 Set 存储,内存增长确认数据集大小
groupBy每个分组是一个流,流过多 OOM限制分组数量

操作符命名对照

Reactor 与 RxJava 的操作符命名基本一致,但存在少数差异:

ReactorRxJava语义
doOnCancelFlowable.doOnCancel / Observable.doOnDispose取消回调
onErrorResumeonErrorResumeNext错误恢复
limitRate—批量 request(Reactor 独有)
limitRequest—限制总请求(Reactor 独有)
switchIfEmptyswitchIfEmpty空流切换
defaultIfEmptydefaultIfEmpty空流默认值

Mono 与 Flux 的专属操作符

Mono 独有

操作符语义
defaultIfEmpty空时提供默认值
switchIfEmpty(Mono)空时切换备用 Mono
hasElement是否有元素
ignoreElement忽略值,只关心终止
then完成后执行下一个 Mono
zipWhen与另一个 Mono 组合

Flux 独有

操作符语义
collectList收集为 List
collectMap收集为 Map
reduce归约
scan累积扫描
window分窗口
buffer缓冲为 List
groupBy分组
sort排序
distinct去重
sample按时间采样
sampleTimeout按时间窗口采样

速查卡片:我最常用的 10 个操作符

  1. map — 数据变换(90% 的链都有)
  2. flatMap — 并发异步展开
  3. filter — 过滤
  4. zip — 多流配对
  5. timeout — 超时控制
  6. retryWhen — 退避重试
  7. onErrorResume — 降级
  8. doOnNext — 调试/监控
  9. subscribeOn — 线程切换
  10. onBackpressureBuffer — 背压控制

阅读导航

上一篇:14.3 v1 验收:RS 合规、背压可观测、文档

下一篇:附录 B 调度器选择指南

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「java」更多文章

  1. 15.3 全书总结与学习路径回顾
  2. 15.2 响应式流处理的演进趋势
  3. 15.1 引擎选型指南