map
用于同步非阻塞的一对一转换flatMap
适用于异步非阻塞的1到N转换这两个区别在方法签名中可以发现:
英文原版:
- map takes a Function
and returns a Flux - flatMap takes a Function
and returns a Flux 中文译文:
- map 接受Function
并返回Flux - flatMap 接受Function
并返回Flux
我们可以将Function
传递给map
,但map
却不知道如何处理发布者。这也导致map
返回的一串不活动的发布者 Flux
。
另一方面,flatMap
期望每个传来的 T
都有 Publisher
。flatMap
知道如何处理它:订阅它并在输出序列中传播其元素。
所以,flatmap
最后总会返回 Flux
类型:flatMap将把每个内部Publisher 展平为所有V的输出序列。
关于1到N转换方面:
对于每个输入元素
,flatMap
会将其映射到 Publisher
。在某些情况下(例如HTTP请求),该发布者将仅发出一项,在这种情况下,我们非常接近异步的 map
。
但这是一种最简化的情况。通常情况下,发布者会发出多个元素,使用 faltmap
就可以比 map
有更为良好的运行效率。
例如,假设您有一个反应性数据库,flatmap
从一系列用户ID,请求返回了每个用户的徽章 Set
集合。最后,flatmap
会返回一个包含所有用户的徽章集合的 Flux
(因为会被压扁flatten
)。
map
真的是同步且非阻塞的吗?️答案是肯定的:操作符应用map
的方式是同步的(一个简单的方法调用,然后操作员发出结果),并且在操作符调用 map
时函数本身不会阻塞这个调用,从这个意义上说是 map
非阻塞的。换句话说,map
不应会引入延迟。这是因为Flux总体上还是异步的。如果阻塞了 Flux
的序列中某个元素,这将影响其余的 Flux
处理,甚至其他 Flux
。
如果你发现使用 map
函数时,会阻塞/引入延迟,但是无法转换并返回 Publisher
发布者,请考虑使用 publishOn / subscribeOn
来抵消在单独线程上的阻塞。