Reactor 操作符

数据在响应式流中的处理,就像流过一条装配流水线。Reactor 既是传送带,又是一个个的装配工或机器人。原材料从源头(最初的 Publisher )流出,经过一个个的装配线中装配工或机器人的工位加工(operator 操作),最终被加工成成品,等待被推送到消费者( subscribe 操作)。

在 Reactor 中,每个操作符对 Publisher 进行处理,然后将 Publisher 包装为另一个新的 Publisher 。就像一个链条,数据源自第一个 Publisher ,然后顺链条而下,在每个环节进行相应的处理。最终,订阅者(Subscriber )终结这个过程。所以, 响应式编程按照链式方式进行开发。

注意,如同 Java Stream 的终端操作,订阅者( Subscriber )在没有订阅( subscribe )到一个发布者( Publisher )之前,什么也不会发生。

如同 Java Stream 的中间操作一样,Reactor 的 Flux 和 Mono 也为我们提供了多种操作符(远多于 Stream ),我们将它们分类如下:

序号 类型 操作符
1 转换 as, cast, collect, collectList, collectMap, collectMultimap, collectSortedList, concatMap, concatMapDelayError, concatMapIterable, elapsed, expand, expandDeep, flatMap, flatMapDelayError, flatMapIterable, flatMapSequential, flatMapSequentialDelayError, groupJoin, handle, index, join, map, switchMap, switchOnFirst, then, thenEmpty, thenMany, timestamp, transform, transformDeferred
2 筛选 blockFirst, blockLast, distinct, distinctUntilChanged, elementAt, filter, filterWhen, ignoreElements, last, next, ofType, or, repeat, retry, single, singleOrEmpty, sort, take, takeLast, takeUntil, takeUntilOther, takeWhile
3 组合 concatWith, concatWithValues, mergeOrderWith, mergeWith, startWith, withLatestFrom, zipWith, zipWithIterable
4 条件 defaultIfEmpty, delayUntil, retryWhen, switchIfEmpty
5 时间 delayElements, delaySequence, delaySubscription, sample, sampleFirst, sampleTimeout, skip, skipLast, skipUntil, skipUntilOther, skipWhile, timeout
6 统计 count, reduce, reduceWith, scan, scanWith
7 匹配 all, any, hasElement, hasElements
8 分组 buffer, bufferTimeout, bufferUntil, bufferUntilChanged, bufferWhen, groupBy, window, windowTimeout, windowUntil, windowUntilChanged, windowWhen, windowWhile
9 事件 doAfterTerminate, doFinally, doFirst, doOnCancel, doOnComplete, doOnDiscard, doOnEach, doOnError, doOnNext, doOnRequest, doOnSubscribe, doOnTerminate, onBackpressureBuffer, onBackpressureDrop, onBackpressureError, onBackpressureLatest, onErrorContinue, onErrorMap, onErrorResume, onErrorReturn, onErrorStop
10 调试 checkpoint, hide, log
11 其它 cache, dematerialize, limitRate, limitRequest, materialize, metrics, name, onTerminateDetach, parallel, publish, publishNext, publishOn, replay, share, subscribeOn, subscriberContext, subscribeWith, tag

接下来我们来挨个学习各类的操作符,如同前面学习响应式流创建一样,讲解操作符时,如果是 Flux 或 Mono 独有的,会在方法名前增加类名前缀。

转换类操作符

转换类的操作符数量最多,平常过程中也是使用最频繁的。

as

将响应式流转换为目标类型,既可以是非响应式对象,也可以是 Flux 或 Mono。

Flux.range(3, 8)
.as(Mono::from)
.subscribe(System.out::println);

cast

将响应式流内的元素强转为目标类型,如果类型不匹配(非父类类型或当前类型),将抛出 ClassCastException ,见图知意:

Flux.range(1, 3)
.cast(Number.class)
.subscribe(System.out::println);

Flux#collect

通过应用收集器,将 Flux 发出的所有元素收集到一个容器中。当此流完成时,发出收集的结果。 Flux 提供了 2 个重载方法,主要区别在于应用的收集器不同,一个是 Java Stream 的 Collector, 另一个是自定义收集方法(同 Java Stream 中 collect 方法):

<R,A> Mono<R> collect(Collector<? super T,A,? extends R> collector);
<E> Mono<E> collect(Supplier<E> containerSupplier,
BiConsumer<E,? super T> collector);

见图知意:

Flux.range(1, 5)
.collect(Collectors.toList())
.subscribe(System.out::println);

Flux#collectList

当此 Flux 完成时,将此流发出的所有元素收集到一个列表中,该列表由生成的 Mono 发出。见图知意:

Flux.range(1, 5)
.collectList()
.subscribe(System.out::println);

Flux#collectMap

将 Flux 发出的所有元素按照键生成器和值生成器收集到 Map 中,之后由 Mono 发出。Flux 提供了 3 个重载方法:

<K> Mono<Map<K,T>> collectMap(Function<? super T,? extends K> keyExtractor);
<K,V> Mono<Map<K,V>> collectMap(Function<? super T,? extends K> keyExtractor,
Function<? super T,? extends V> valueExtractor);
<K,V> Mono<Map<K,V>> collectMap(Function<? super T,? extends K> keyExtractor,
Function<? super T,? extends V> valueExtractor,
Supplier<Map<K,V>> mapSupplier);

它们的主要区别在于是否提供值生成器和初始的Map,意同 Java Stream 中的 Collectors#toMap 。见图知意:

Flux.just(1, 2, 3, 4, 5, 3, 1)
.collectMap(n -> n, n -> n + 100)
.subscribe(System.out::println);

Flux#collectMultimap

collectMultimap 与 collectMap 的区别在于,map 中的 value 类型不同,一个是集合,一个是元素。 collectMultimap 对于流中出现重复的 key 的 value,加入到了集合中,而 collectMap 做了替换。在这点上,reactor 不如 Java Stream 中的 Collectors#toMap 方法,没有提供 key 重复时的合并函数。也提供了 3 个重载方法。

<K> Mono<Map<K,Collection<T>>> collectMultimap(Function<? super T,? extends K> keyExtractor);
<K,V> Mono<Map<K,Collection<V>>> collectMultimap(Function<? super T,? extends K> keyExtractor,
Function<? super T,? extends V> valueExtractor);
<K,V> Mono<Map<K,Collection<V>>> collectMultimap(Function<? super T,? extends K> keyExtractor,
Function<? super T,? extends V> valueExtractor,
Supplier<Map<K,Collection<V>>> mapSupplier)

见图知意:

Flux.just(1, 2, 3, 4, 5, 3, 1)
.collectMultimap(n -> n, n -> n + 100)
.subscribe(System.out::println);

Flux#collectSortedList

将 Flux 发出的元素在完成时进行排序,之后由 Mono 发出。Flux 提供了 2 个重载方法:

Mono<List<T>> collectSortedList();
Mono<List<T>> collectSortedList(@Nullable Comparator<? super T> comparator);

见图知意:

Flux.just(1, 3, 5, 3, 2, 5, 1, 4)
.collectSortedList()
.subscribe(System.out::println);

总结

本篇我们介绍了 Reactor 操作符的分类,之后介绍了部分转换类操作符,讲解示例时都是单个操作符,相信大家都能理解。

今天的内容就学到这里,我们下篇继续学习 Reactor 的操作符。

源码详见:https://github.com/crystalxmumu/spring-web-flux-study-note 下 02-reactor-core-learning

模块下 ReactorTransformOperatorTest 测试类。

参考

  1. Reactor 3 Reference Guide
  2. Reactor 3 中文指南

学习响应式编程 Reactor (4) - reactor 转换类操作符(1)的更多相关文章

  1. 学习响应式编程 Reactor (5) - reactor 转换类操作符(2)

    Reactor 操作符 上篇文章我们将 Flux 和 Mono 的操作符分了 11 类,我们来继续学习转换类操作符的第 2 篇. 转换类操作符 转换类的操作符数量最多,平常过程中也是使用最频繁的. F ...

  2. 学习响应式编程 Reactor (1) - 响应式编程

    响应式编程 命令式编程(Imperative Programing),是一种描述计算机所需做出的行为的编程范式.详细的命令机器怎么(How)去处理以达到想要的结果(What). 声明式编程(Decla ...

  3. 学习响应式编程 Reactor (2) - 初识 reactor

    Reactor Reactor 是用于 Java 的异步非阻塞响应式编程框架,同时具备背压控制的能力.它与 Java 8 函数式 Api 直接集成,比如 分为CompletableFuture.Str ...

  4. 学习响应式编程 Reactor (3) - reactor 基础

    Reactor Reactor 项目的主要 artifact 是 reactor-core,这是一个基于 Java 8 的实现了响应式流规范的响应式库. Reactor 提供了实现 Publisher ...

  5. 响应式编程简介之:Reactor

    目录 简介 Reactor简介 reactive programming的发展史 Iterable-Iterator 和Publisher-Subscriber的区别 为什么要使用异步reactive ...

  6. 响应式编程系列(一):什么是响应式编程?reactor入门

    响应式编程 系列文章目录 (一)什么是响应式编程?reactor入门 (二)Flux入门学习:流的概念,特性和基本操作 (三)Flux深入学习:流的高级特性和进阶用法 (四)reactor-core响 ...

  7. Project Reactor 响应式编程

    目录 一. 什么是响应式编程? 二. Project Reactor介绍 三. Reactor核心概念 Flux 1. just() 2. fromArray(),fromIterable()和 fr ...

  8. SpringBoot 2.x (14):WebFlux响应式编程

    响应式编程生活案例: 传统形式: 一群人去餐厅吃饭,顾客1找服务员点餐,服务员把订单交给后台厨师,然后服务员等待, 当后台厨师做好饭,交给服务员,经过服务员再交给顾客1,依此类推,该服务员再招待顾客2 ...

  9. 响应式编程(Reactive Programming)(Rx)介绍

    很明显你是有兴趣学习这种被称作响应式编程的新技术才来看这篇文章的. 学习响应式编程是很困难的一个过程,特别是在缺乏优秀资料的前提下.刚开始学习时,我试过去找一些教程,并找到了为数不多的实用教程,但是它 ...

随机推荐

  1. 二、postman断言及正则表达式取值

    postman老式断言与新式断言总结:本文以微信开发者文档为例 断言处如图所示 一.老式断言 老式断言总结:var variables相当于代码中定义的变量,test['']=true;相当于pyth ...

  2. 【转】python SQLAlchemy

    数据库表是一个二维表,包含多行多列. 把一个表的内容用Python的数据结构表示出来的话,可以用一个list表示多行,list的每一个元素是tuple,表示一行记录,比如,包含id和name的user ...

  3. 10个 解放双手的 IDEA 插件,这些代码都不用写(第二弹)

    本文案例收录在 https://github.com/chengxy-nds/Springboot-Notebook 大家好,我是小富~ 鸽了很久没发文,不写文章的日子真的好惬意,每天也不用愁着写点什 ...

  4. 类的两个装饰器classmethod、staticethod和内置魔术方法

    一.两个装饰器@classmethod.@staticmethod @classmethod:把类中的绑定方法变成一个类方法,cls 就等于类名 有什么用? 1.在方法中任然可以引用类中的静态变量 2 ...

  5. 老板让我重构项目,我想首先应该服务治理---eureka服务治理深入浅出

    目录 什么是服务治理 Eureka调用过程 Eureka单机注册 Eureka 单机启动 单机注册 集群注册 客户调用 Eureka集群注册 idea 如何同一个项目启动多次 Eureka自我保护 为 ...

  6. 33.2.NIO

    4.1概述[理解] BIO Blocking IO,阻塞型IO NIO No Blocking IO,非阻塞型IO 阻塞IO的弊端 在等待的过程中,什么事也做不了 非阻塞IO的好处 不需要一直等待,当 ...

  7. git远端账号问题

    1. gitlab密码修改后git因保存密码无法下载,403 在.git/config添加如下 [credential] helper = store 添加了此项配置之后, github的账号信息就会 ...

  8. 040.Python进程和Join

    一  进程相关介绍 1.1 进程的概念(process) 进程就是正在运行的程序,它是操作系统中,资源分配的最小单位 资源分配:分配的是cpu和内存等物理资源 进程号是程的唯标识 同-个程序执行两次之 ...

  9. Centos 7.4搭建es7.12.0+Skywalking7.8.5

    Skywalking整体架构图和分布式追踪系统原理:https://blog.csdn.net/weixin_39866487/article/details/111581322 软件包版本1.ela ...

  10. python基础之流程控制(if判断和while、for循环)

    程序执行有三种方式:顺序执行.选择执行.循环执行 一.if条件判断 1.语句 (1)简单的 if 语句 (2)if-else 语句 (3)if-elif-else 结构 (4)使用多个 elif 代码 ...