RxJava 学习笔记<八> 译 Transformation of sequences

 Transformation of sequences

在本章中,咱们将看到改变数据格式的方法。在现实世界中,observable 能够是任何类型的。数据的格式已是咱们想要的格式,这是不常见的。更有可能的状况是,这些值须要扩展、裁剪、评估或简单地替换为其余值。ios

这将由 oprations 的三个基本类别来完成。map 和 flatMap 是第三类的基本方法。在文献中,您经常会发现它们被称为“bind”,至于缘由超出了本指南的范围。git

Ana(morphism) T --> Observable<T>
Cata(morphism) Observable<T> --> T
Bind Observable<T1> --> Observable<T2>程序员

在最后一章中,为了方便起见,咱们介绍了 Subscriber 的一个实现。咱们将在本章的示例中继续使用它。github

map

转换的基本方法是 map(在相似由SQL启发的系统(如LINQ)中也称为“SELECT”)。它接受一个转换函数,它接受一个项并返回任何类型的新项。返回的可观测值由转换函数返回的值组成。编程

在第一个例子中,咱们将取一个整数序列,并将它们增长3。异步

输出:函数式编程

这就是 map 作的事情,例如经过使用 Observable.range(3,4)。在下面,咱们将作一些更实际的事情。生产者将像许多 UI 一般所作的那样,以字符串的形式发出数值,而后使用map将它们转换为更可处理的整数格式。函数

输出:spa

这种转换很是简单,咱们也能够在订阅方进行,但这将是一种糟糕的责任划分。在开发生产者方面时,您但愿以尽量简洁和最方便的方式呈现事物。你不会转储原始数据,让消费者本身去发现。在咱们的示例中,既然咱们说API生成整数,它就应该这样作。Transfomation操做符容许咱们将初始序列转换为咱们想要公开的API。调试

cast and ofType

cast 是将 item 转换为另外一种类型的简写。若是您有一个 Observable<Object>,您知道它只会发出T类型的值,那么在lambda函数中强制转换可观察到的值比进行强制转换要简单得多。

输出:

若是不能将全部项强制转换为指定类型,则强制转换方法将失败。

输出:

若是您但愿忽略此类状况,则可使用ofType方法。这将过滤没法强制转换的项,而后将序列转换为所需的类型。

输出:

timestamp and timeInterval

timestamp 和 timeInterval 方法使咱们可以用有关序列的异步性质的信息来丰富咱们的值。timestamp将值转换 Timestamped<T> 类型,该类型包含原始值,以及发出事件时的时间戳

public final Observable<Timestamped<T>> timestamp()

这里是一个例子:

输出:

时间戳使咱们能够看到这些项大约是隔100毫秒发出的(Java对此几乎没有提供保证)。

若是咱们更感兴趣的是自上一项以后已通过去了多少时间,而不是发出项目的绝对时刻,咱们可使用timeInterval方法

public final Observable<TimeInterval<T>> timeInterval()

按照与前面相同的顺序使用timeInterval:

输出:

timestamp 和TimeInterval捕获的信息对于日志记录和调试很是有用。它是Rx获取序列异步性信息的一种方法。

materialize and dematerialize

materialize 对于日志记录也颇有用,materialize 将序列转换为它的元数据表示形式。

通知类型能够表示任何事件,即值的释放、错误或完成。注意,在上面的图中,“onCompleted”的发射并不意味着序列的结束,由于序列其实是随后结束的。下面是一个例子

输出:

Notification type包含用于肯定事件类型以及携带值或Throwable(若是有的话)的方法。

dematerialize 将逆转 materialize 的效果,使 materialized observable 返回到它的正常形式。

flatMap

map取一个值,而后返回另外一个值,替换顺序为一对一的项。flatMap 将用任意数量的项替换项目,包括零项或无穷项。flatMap 的转换方法从源 observable 中获取值,并对每一个值返回一个新的 observable,发射新值。

由 flatMap 返回的可观测值将发出由转换函数产生的全部可观测值发出的全部值。来自同一可观测值的值将是有序的,但它们可能与来自其余可观测值的值交织在一块儿。

让咱们从一个简单的例子开始,其中 FlapMap 应用于一个具备单个值的 observable ,将发出一个单独的值。FlapMap将把它转换为一个即0到2之间的范围的 observable。这个可观测值是在最终的可观测值中发射出来的。

输出:

当 flatMap 应用于多个值的 observable ,每一个值将产生一个新的 observable , values 将发出一、2和3。获得的 observable 将分别发出值[0]、[0,1]和[0,1,2]。这些值将被平铺在一块儿,造成一个可观察到的值:由FlapMap返回的值。

输出:

与 map 很是类似,platMap 的输入和输出类型能够自由地有所不一样。在下一个示例中,咱们将把整数转换为字符。

输出:

虽然每一个值都必须产生一个可观察的值,可是没有什么能够阻止这个可观察到的值是空的。咱们能够用它来过滤序列,同时对其进行转换。

输出:

此示例将致使打印整个字母表而不会出错,即便初始范围超过字母表的范围。

到目前为止,在咱们的flatMap 示例中,值按顺序排列:首先是来自第一个可观测值的全部值,而后是来自第二个可观测值的全部值。虽然这彷佛很直观,特别是在来自同步环境时,但须要注意的是,状况并不老是如此。FlapMap返回的可观察值一旦可用就会发出值。在咱们的例子中,全部的观测值都是同步准备好的。为了证实这一点,咱们使用区间方法构造异步观测值。

输出:

咱们从值100和150开始,将它们用做在 FlapMap 中建立的异步观测值的间隔期间。由于间隔发出数字1,2,3...在这两种状况下,为了更好地区分这两个可观察到的值,咱们用每一个可观察到的操做所依据的间隔时间替换这些值。

咱们能够看到,这两个观测值交织在一块儿。

concatMap

尽管在函数式编程中,FlapMap与一个很是常见的操做符同名,但咱们发现它的行为并不彻底像函数式程序员所指望的那样。有一个运算符不会交错序列,名为contatMap,由于它与咱们稍后将看到的conat运算符相关。

输出:

咱们能够在输出中看到这两个序列是分开的。请注意,contatMap操做符只适用于终止序列:在当前序列终止以前,它不能移动到下一个序列。因为这个缘由,咱们不得不用Take来限制区间的无穷序列。

flatMapIterable

flatMap 和 concatMap 将由它们的选择器函数生成的一系列可观察到的东西平铺成一个可观察的东西。咱们还可使用FlapMapIterable来平抑一个迭代序列。这相似于 flatMap ,只有咱们的选择器函数建立迭代。

若是取代 Observable.range ,咱们可能写下面的迭代器

输出:

正如预期的那样,咱们建立的三个迭代在一个可观察的序列中被压平(flattened)。

做为一名Rx开发人员,建议您将数据表示为可观察序列,并避免将可观测序列与迭代序列相混合。可是,当您的数据已经采用集合的格式时(例如,由于标准Java操做会这样返回它们),只使用它们而不首先转换它们可能会更简单或更快。FlapMapIterable还消除了选择交错与否的须要:FlapMapIterable不会交错,就像您指望从同步FlapMap中获得的同样。

还有第二个重载,它容许您将可迭代中的每一个值与生成可迭代的值组合在一块儿。

输出:

在这里,咱们将迭代范围中的每一个值乘以播种范围的值:[1*1]、[1*二、2*2]、[1*三、2*三、3*3]。

Java缺少对其标准集合进行映射的方法。所以,在种子值消失以前不可能转换可迭代值(这里是i->范围(1,i)中的i)。在这里,咱们的可迭代仅仅是一个列表,因此咱们能够在返回它以前修改它。可是,若是咱们的可迭代不是一个集合,咱们将不得不本身实现一个迭代映射,或者手动将修改后的值收集到一个新的集合中并返回它。这个重载的FlapMapIterable使咱们没必要将这种丑陋插入到管道的中间。

懒惰的概念在Java中并不常见,所以您可能会对哪些类型的可迭代不是集合感到困惑。为了举例说明,请考虑下面的可迭代性,它懒散地生成一个范围。它容许咱们经过计算上一个值的下一个值来迭代一个范围。这样,咱们节省了存储整个范围的内存。

输出:

原文连接:

https://github.com/Froussios/Intro-To-RxJava/blob/master/Part%202%20-%20Sequence%20Basics/5.%20Transformation%20of%20sequences.md

相关文章
相关标签/搜索