以下代码起作用:
// emitting employees...
.flatMap(employee -> {
boolean isAlive = employee.isAlive();
return Mono.just(isAlive)
.flatMap(myBoolean -> {
if (myBoolean) {
return Mono.empty();
}
else {
return Mono.just(employee);
}
});
})
但是我想知道为什么在处理.map
时不能使用myBoolean
(当NullPointerException返回null时)
.map(myBoolean -> {
if (myBoolean) {
return null;
}
else {
return employee;
}
});
我相信我对map
与flatMap
在Java 8流中,我了解map
和flatMap
之间的区别(对于收到的每个项目,map
发出1,flatMap
发出N)
但是在Reactor中,我有点困惑。我认为map
和flatMap
都会为收到的每个元素发出1个项目,不同之处在于map
会以Mono
的形式发出,而flatMap
却不会。没错要发出N个物品,我将使用flatMapMany
。
预先感谢您的解释!
答案 0 :(得分:2)
使用map方法映射Mono
的内容时,不能提供null作为映射结果,因为这将导致
订阅期间java.lang.NullPointerException: The mapper returned a null value.
。
Mono
可以为空,也可以包含有效的对象。
根据Project Reactor的源代码,Mono
的内容不能为null。
因此,在这种情况下,有效的解决方案是使用flatMap
。
答案 1 :(得分:2)
从Reactor java doc
map
:通过对其应用同步函数来变换此Mono发出的项目。
flatMap
:异步转换此Mono发出的项,并返回另一个Mono发出的值。
在所有情况下,您都无法返回null
。设计完全禁止这样做。 map
和flatMap
之间的主要区别是第二个返回一个Mono。这样可以对数据库,Web服务等进行异步调用。
因此,flatMap
应该用于执行其他异步操作。如果返回Mono.just(...)
,它不是很有用。我们可能会像您一样在某些情况下使用flatMap返回Mono.empty()
。这是一种常见的模式。
以下是替代代码,用于发出带有条件的新对象:
.handle(myBoolean, sink -> {
if (!myBoolean) {
sink.next(employee);
} // else the Mono would be empty ...
});
答案 2 :(得分:1)
那是因为flatMap
会尝试将内部Mono拆开。表示该值将为null,但将有一个类型。
另一方面,map
会将Mono<A>
转换为Mono<B>
。 null没有类型,这就是为什么您不能这样做。
答案 3 :(得分:0)
流中任何地方的null
都会抛出NPE: Mapper returned a null value
。无论map
还是flatMap
。这是设计使然。
关于flatMap
的简短说明:它热切地订阅其内部流(在您的情况下为Mono.empty()
或Mono.just(..)
),并随着内部流不断发出元素而进行动态合并。这就是为什么您可以保证使用flatMap
订购的原因。