在Reactor中的.map()与.flatMap()中返回null

时间:2019-10-03 09:08:11

标签: java reactor

以下代码起作用:

// 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;
                }
            });

我相信我对mapflatMap

缺乏了解

在Java 8流中,我了解mapflatMap之间的区别(对于收到的每个项目,map发出1,flatMap发出N)

但是在Reactor中,我有点困惑。我认为mapflatMap都会为收到的每个元素发出1个项目,不同之处在于map会以Mono的形式发出,而flatMap却不会。没错要发出N个物品,我将使用flatMapMany

预先感谢您的解释!

4 个答案:

答案 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。设计完全禁止这样做。 mapflatMap之间的主要区别是第二个返回一个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订购的原因。