Flux 和 Mono 中的 compose() vs. transform() vs. as() vs. map()
compose() vs. transform() vs. as() vs. map() in Flux and Mono
最近,我决定尝试 spring 5 和 projectreactor.io (io.projectreactor:3.1.1)。
有谁知道使用这个函数的最佳情况是什么?使用它们各自的优缺点以及应该在哪里使用它们?
好的例子会有所帮助。
这里有两类截然不同的运算符:
在 Flux
本身上工作的运算符
transform
和transformDeferred
用于代码互化
当您定期组成运算符链并且您的应用程序中有常见的运算符使用模式时,您可以共享此代码或使用 transform
和 transformDeferred
为其赋予更具描述性的名称。
两者的区别在于何时应用互化运算符:transform
在实例化时应用它们,而transformDeferred
在订阅时应用它们(允许用于动态选择添加的运算符)。
查看 reference documentation 了解更多详细信息和示例。
注意:transformDeferred
在 3.3.0
之前的版本中被称为 compose
as
这是将 Function
应用于整个 Flux
同时保持整个代码流畅的快捷方式。
与 transform*
运算符 的主要区别在于,此运算符不强制执行特定的 return 类型。它全部由您使用的 Function
驱动,例如可以用于以流畅的风格使用 StepVerifier
进行测试:
Flux.just("test")
.map(String::length)
.as(StepVerifier::create)
//from there on we're dealing with the StepVerifier API
.expectNext(4)
.verifyComplete();
javadoc 中显示的示例使用这种方法使用 Mono::from
转换为 Mono
,这有点令人困惑,因为 return 类型非常接近 [=13] =].
请注意,此方法还可以帮助以工厂方法样式实现的外部运算符“扩展”Flux
API
以reactor-addons
MathFlux
为例,比较:
MathFlux.sumInt(Flux.range(1, 10)
.map(i -> i + 2)
.map(i -> i * 10))
.map(isum -> "sum=" + isum);
收件人:
Flux.range(1, 10)
.map(i -> i + 2)
.map(i -> i * 10)
.as(MathFlux::sumInt)
.map(isum -> "sum=" + isum)
(这可以帮助您处理与 Kotlin 不同的事实,Java 没有扩展方法:))
处理通过 Flux
的数据的运算符
map
都是关于数据的。它对源中的每个元素应用 1-1 转换函数,因为它们变得可用。
在上面的 MathFlux 示例中,map
连续用于为每个原始整数加 2,然后再次将序列中的每个数字乘以 10,最后第三次生成 String
出每笔款项。
我发现 reference documentation 中的示例有点难理解
所以制作了以下程序来围绕转换与组合的概念。
fnstatefull = flux -> {
Flux<String> f = flux.filter(color -> {
//only reds are allowed
return color.equalsIgnoreCase("red");
});
//applies mapping 'toUpperCase' based on the external control 'toUpper'
if(toUpper) {
f= f.map(String::toUpperCase);
}
return f;
};
转换
运算符在通量实例化时应用。
fnstatefull 对以下两个订阅者的行为相同。
Flux<String> f = Flux.just("red", "green", "blue");
toUpper = false;
f = f.transform(fnstatefull);
toUpper = true;
f.subscribe(op -> log.error("ONE>>>" + op));
toUpper = false;
f.subscribe(op -> log.error("TWO>>>" + op));
输出
ReactordemoApplication - ONE>>>red
ReactordemoApplication - TWO>>>red
撰写
运算符在订阅时应用到通量。
fnstatefull 对以下每个订阅者的行为都不同。
Flux<String> f = Flux.just("red", "green", "blue");
toUpper = false;
f = f.compose(fnstatefull);
toUpper = true;
f.subscribe(op -> log.error("ONE>>>" + op));
toUpper = false;
f.subscribe(op -> log.error("TWO>>>" + op));
输出
ReactordemoApplication - ONE>>>RED
ReactordemoApplication - TWO>>>red
最近,我决定尝试 spring 5 和 projectreactor.io (io.projectreactor:3.1.1)。
有谁知道使用这个函数的最佳情况是什么?使用它们各自的优缺点以及应该在哪里使用它们?
好的例子会有所帮助。
这里有两类截然不同的运算符:
在 Flux
本身上工作的运算符
transform
和transformDeferred
用于代码互化
当您定期组成运算符链并且您的应用程序中有常见的运算符使用模式时,您可以共享此代码或使用 transform
和 transformDeferred
为其赋予更具描述性的名称。
两者的区别在于何时应用互化运算符:transform
在实例化时应用它们,而transformDeferred
在订阅时应用它们(允许用于动态选择添加的运算符)。
查看 reference documentation 了解更多详细信息和示例。
注意:transformDeferred
在 3.3.0
compose
as
这是将 Function
应用于整个 Flux
同时保持整个代码流畅的快捷方式。
与 transform*
运算符 的主要区别在于,此运算符不强制执行特定的 return 类型。它全部由您使用的 Function
驱动,例如可以用于以流畅的风格使用 StepVerifier
进行测试:
Flux.just("test")
.map(String::length)
.as(StepVerifier::create)
//from there on we're dealing with the StepVerifier API
.expectNext(4)
.verifyComplete();
javadoc 中显示的示例使用这种方法使用 Mono::from
转换为 Mono
,这有点令人困惑,因为 return 类型非常接近 [=13] =].
请注意,此方法还可以帮助以工厂方法样式实现的外部运算符“扩展”Flux
API
以reactor-addons
MathFlux
为例,比较:
MathFlux.sumInt(Flux.range(1, 10)
.map(i -> i + 2)
.map(i -> i * 10))
.map(isum -> "sum=" + isum);
收件人:
Flux.range(1, 10)
.map(i -> i + 2)
.map(i -> i * 10)
.as(MathFlux::sumInt)
.map(isum -> "sum=" + isum)
(这可以帮助您处理与 Kotlin 不同的事实,Java 没有扩展方法:))
处理通过 Flux
的数据的运算符
map
都是关于数据的。它对源中的每个元素应用 1-1 转换函数,因为它们变得可用。
在上面的 MathFlux 示例中,map
连续用于为每个原始整数加 2,然后再次将序列中的每个数字乘以 10,最后第三次生成 String
出每笔款项。
我发现 reference documentation 中的示例有点难理解
所以制作了以下程序来围绕转换与组合的概念。
fnstatefull = flux -> {
Flux<String> f = flux.filter(color -> {
//only reds are allowed
return color.equalsIgnoreCase("red");
});
//applies mapping 'toUpperCase' based on the external control 'toUpper'
if(toUpper) {
f= f.map(String::toUpperCase);
}
return f;
};
转换
运算符在通量实例化时应用。
fnstatefull 对以下两个订阅者的行为相同。
Flux<String> f = Flux.just("red", "green", "blue");
toUpper = false;
f = f.transform(fnstatefull);
toUpper = true;
f.subscribe(op -> log.error("ONE>>>" + op));
toUpper = false;
f.subscribe(op -> log.error("TWO>>>" + op));
输出
ReactordemoApplication - ONE>>>red
ReactordemoApplication - TWO>>>red
撰写
运算符在订阅时应用到通量。
fnstatefull 对以下每个订阅者的行为都不同。
Flux<String> f = Flux.just("red", "green", "blue");
toUpper = false;
f = f.compose(fnstatefull);
toUpper = true;
f.subscribe(op -> log.error("ONE>>>" + op));
toUpper = false;
f.subscribe(op -> log.error("TWO>>>" + op));
输出
ReactordemoApplication - ONE>>>RED
ReactordemoApplication - TWO>>>red