操作符
1、创建:
just()
Flux<String> fruitFlux = Flux.just("Apple", "Orange", "Grape", "Banana", "Strawberry");
- 基于数组、集合、stream
Integer[] array = new Integer[]{1,2,3,4,5,6};
Flux.fromArray(array);
List<Integer> list = Arrays.asList(array);
Flux.fromIterable(list);
Stream<Integer> stream = list.stream();
Flux.fromStream(stream);
-
range(n,m):创建起始值为n,每个元素递增1,总共m个元素Flux.range(1, 5); // 1,2,3,4,5 -
interval():每隔相应时间发送一次
2、订阅:subscribe()
订阅前什么都不会发生:只有订阅方法调用的时候,才会触发数据流
fruitFlux.subscribe(
f -> System.out.println("Here's some fruit: " + f);
);
3、测试:StepVerifier订阅响应式类型,然后对流中流动的数据应用断言,最后验证流以预期方式完成。
StepVerifier.create(fruitFlux)
.expectNext("Apple")
.expectNext("Orange")
.expectNext("Grape")
.expectNext("Banana")
.expectNext("Strawberry")
.verifyComplete();
expectNext用于测试下一个期望的数据元素,expectErrorMessage用于校验下一个元素是否为错误信号,expectComplete用于测试下一个元素是否为完成信号。
4、合并:mergeWith()
@Test
public void mergeFluxes() {
Flux<String> characterFlux = Flux
.just("Garfield", "Kojak", "Barbossa")
.delayElements(Duration.ofMillis(500)); //减慢发送速度,每0.5秒发送一个
Flux<String> foodFlux = Flux
.just("Lasagna", "Lollipops", "Apples")
.delaySubscription(Duration.ofMillis(250))//延迟250ms之后再发送数据
.delayElements(Duration.ofMillis(500));
Flux<String> mergedFlux = characterFlux.mergeWith(foodFlux);
StepVerifier.create(mergedFlux)
.expectNext("Garfield")
.expectNext("Lasagna")
.expectNext("Kojak")
.expectNext("Lollipops")
.expectNext("Barbossa")
.expectNext("Apples")
.verifyComplete(); //合并顺序和发送顺序一致
}
5、压缩:zip():对两个Flux流每次各取一个元素,合并为一个二元组(Tuple2),也可以指定function接口
6、过滤
skip(n):跳过前n项数据skip(Duration.ofSeconds(n)):发出任何值之前等待n秒?take(n):只发出前n项数据take(Duration.ofMillis(n)):distinct():去重filter():自定义过滤规则,满足规则的留下
@Test
public void filter() {
Flux<String> nationalParkFlux = Flux.just(
"Yellowstone", "Yosemite", "Grand Canyon","Zion", "Grand Teton")
.filter(np -> !np.contains(" "));//不含有空格的留下
StepVerifier.create(nationalParkFlux)
.expectNext("Yellowstone", "Yosemite", "Zion")
.verifyComplete();
}
7、映射
map():
@Test
public void map() {
Flux<Player> playerFlux = Flux
.just("Michael Jordan", "Scottie Pippen", "Steve Kerr")
.map(n -> {
String[] split = n.split("\s"); //将名字的名和姓分开
return new Player(split[0], split[1]); //映射为有名有姓的运动员
});
StepVerifier.create(playerFlux)
.expectNext(new Player("Michael", "Jordan"))
.expectNext(new Player("Scottie", "Pippen"))
.expectNext(new Player("Steve", "Kerr"))
.verifyComplete();
}
flatmap():异步。将每个元素映射为流,再将这些流合并为大的数据流
@Test
public void flatMap() {
Flux<Player> playerFlux = Flux
.just("Michael Jordan", "Scottie Pippen", "Steve Kerr")
.flatMap(n -> Mono.just(n).map(p -> {
String[] split = p.split("\s");
return new Player(split[0], split[1]); //将一个元素映射为只有一个数据的流
})
.subscribeOn(Schedulers.parallel()) //指示每个订阅应该在一个并行线程中
);
List<Player> playerList = Arrays.asList(
new Player("Michael", "Jordan"),
new Player("Scottie", "Pippen"),
new Player("Steve", "Kerr"));
StepVerifier.create(playerFlux)
.expectNextMatches(p -> playerList.contains(p))
.expectNextMatches(p -> playerList.contains(p))
.expectNextMatches(p -> playerList.contains(p))
.verifyComplete();
}
subscribeOn() :指定了应该如何并发地处理订阅。可以使用 Schedulers 程序中的一个静态方法指定要使用的并发模型。调度程序支持多个并发模型:
使用 flatMap() 和 subscribeOn() 的好处是,可以通过将工作分成多个并行线程来增加流的吞吐量。但由于这项工作是并行完成的,无法保证先完成哪项工作,因此无法知道产生的 Flux 中排放的项目的顺序。因此,StepVerifier 只能验证发出的每个项是否存在于 Player 对象的预期列表中,并且在 Flux 完成之前将有三个这样的项。
8、缓冲:buffer() 将数据流分解成指定大小的数据块
@Test
public void buffer() {
Flux<String> fruitFlux = Flux.just(
"apple", "orange", "banana", "kiwi", "strawberry");
Flux<List<String>> bufferedFlux = fruitFlux.buffer(3);
StepVerifier
.create(bufferedFlux)
.expectNext(Arrays.asList("apple", "orange", "banana"))
.expectNext(Arrays.asList("kiwi", "strawberry"))
.verifyComplete();
}
将buffer() 与 flatMap() 结合使用时,它可以并行处理每个 List 集合:
Flux.just("apple", "orange", "banana", "kiwi", "strawberry")
.buffer(3)
.flatMap(x ->
Flux.fromIterable(x)
.map(y -> y.toUpperCase())
.subscribeOn(Schedulers.parallel())
.log() //日志
).subscribe();
9、逻辑
any():任意一个满足条件all():全部都满足条件