问题
The following piece of code works :
// emitting employees...
.flatMap(employee -> {
boolean isAlive = employee.isAlive();
return Mono.just(isAlive)
.flatMap(myBoolean -> {
if (myBoolean) {
return Mono.empty();
}
else {
return Mono.just(employee);
}
});
})
But I was wondering why I can't use a .map
upon processing myBoolean
(NullPointerException when it returns the null)
.map(myBoolean -> {
if (myBoolean) {
return null;
}
else {
return employee;
}
});
I believe I lack some understanding about the map
versus flatMap
In Java 8 streams I understand the difference between map
and flatMap
(for each item received, map
emits 1, flatMap
emits N)
But in Reactor I'm a bit confused. I thought that both map
and flatMap
emit 1 item for each element received, the difference would be that the map
emits it as a Mono
while flatMap
doesn't. To emit N items, I would use flatMapMany
.
Thanks in advance for your explanations !
回答1:
From Reactor java doc
map
: Transform the item emitted by this Mono by applying a synchronous function to it.
flatMap
: Transform the item emitted by this Mono asynchronously, returning the value emitted by another Mono.
In all cases, you cannot return null
. It is simply forbidden by design. The main difference between map
and flatMap
is that the second one returns a Mono. This allows to perform an asynchronous call to something like a data base, a web service, etc.
So flatMap
should be used to performed another asynchronous stuff. It's not very useful if you return a Mono.just(...)
. We may use flatMap to return Mono.empty()
in some condition as you did. It is a frequent pattern.
Here an alternative code to emit a new object with a condition:
.handle(myBoolean, sink -> {
if (!myBoolean) {
sink.next(employee);
} // else the Mono would be empty ...
});
回答2:
That is because flatMap
will try to unwrap the inner mono in the outer mono. Meaning the value will be null but there will be a type..
On the other hand map
will transform the Mono<A>
to Mono<B>
. null has no type and that is why you cannot do that.
回答3:
When mapping a content of Mono
using map method, you cannot provide null as a mapping result, because that will result in the
java.lang.NullPointerException: The mapper returned a null value.
during the subscription.
The Mono
can be either empty or it has to contain a valid object.
According to the source code of Project Reactor, the content of a Mono
cannot be null.
So in this case the valid solution is using the flatMap
.
回答4:
A null
anywhere in your stream will throw a NPE: Mapper returned a null value
. No matter map
or flatMap
. It is by design.
A short note on flatMap
: It eagerly subscribes to its inner streams (in your case, Mono.empty()
or Mono.just(..)
) and does a dynamic merge as the inner streams keep emitting elements. That's why you can guarantee order with flatMap
.
来源:https://stackoverflow.com/questions/58215810/returning-a-null-in-a-map-versus-flatmap-in-reactor