RxJava 之变换操作符和过滤操作符

RxJava 的变换操作符主要包括以下几种

  • map():对序列的每一项都用一个函数来变换 Observable 发射的数据序列
  • flatMap()、contactMap() 和 FlatMapIterable():将 Observable 发射的数据集合变换为 Observables 集合,然后将这些 Observable 发射的数据平坦化地放进一个单独的 Observable 中
  • switchMap():将 Observable 发射的数据集合变换为 Observables 集合,然后只发射这些 Observables 最近发射过的数据
  • scan():对 Observable 发射的每一个数据项应用一个函数,然后按顺序依次发射每一个值
  • groupBy():将 Observable 拆分为 Observable 集合,将原始 Observable 发射的数据按 Key 分组,每一个 Observable 发射一组不同的数据
  • buffer():定期从 Observable 手机数据到一个集合,然后把这些数据集合打包发射,而不是一次发射一个
  • window():定期将来自 Observable 的数据拆分成一些 Observable 窗口,然后发射这些窗口,而不是每次发射一项
  • cast():在发射之前强制将 Observable 发射的所有数据转换为指定类型。

RxJava 的过滤操作符主要包含以下几种

  • filter():过滤数据
  • takeLast():只发射最后的 N 项数据
  • last():只发射最后一项数据
  • lastOrDefault():只发射最后一项数据,如果 Observable 为空,则发射默认值
  • takeLastBuffer():将最后的 N 项数据当做单个数据发射
  • skip():跳过开始的 N 项数据
  • skipLast():跳过最后的 N 项数据
  • take():只发射开始的 N 项数据
  • first():只发射第一项数据
  • elementAt():发射第 N 项数据
  • sample()、throttleLast():定期发射 Observable 最近的数据
  • throttleFirst():定期发射 Observable 发射的第一项数据
  • throttleWithTimeout()、debounce():只有当 Observable 在指定的时间段后还没有发射数据时,才发射一个数据量
  • timeout():如果在一个指定的时间段后还没发射数据,就发射一个异常
  • distinct():过滤掉重复的数据
  • distinctUntilChanged():过滤掉连续重复的数据
  • ofType():只发射指定类型的数据
  • ignoreElements():丢弃所有的正常数据,只发射错误或完成通知

1. map 和 flatMap

  1. map 对 Observable 发射的每一项数据应用一个函数,执行变换操作,然后发射这些结果的 Observable。RxJava 将这个操作符实现为 map 函数,这个操作符默认不在任何特定的调度器上执行。

  2. flatmap 操作符 FlatMap 将一个发射数据的 Observable 变换为多个 Observable,然后将他们发射的数据合并后放进一个单独的 Observable。FlatMap 操作符使用一个指定的函数对原始 Observable 发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的 Observable,然后 flatMap 合并这些 Observable 发射的数据,最后将合并后的结果当做自己的数据序列发射。

map 和 flatMap 对比

User user = new User();
user.setName("tony");
user.setAddresses(new ArrayList<>());
user.getAddresses().add(new Address("tianHe"));
user.getAddresses().add(new Address("yueXiu"));
user.getAddresses().add(new Address("haiZhu"));

Observable.just(user)
        .map(User::getAddresses)
        .subscribe(addresses -> {
            for (Address address : addresses) {
                System.out.println(address.getStreet());
            }
        });

Observable.just(user)
        .flatMap((Function<User, ObservableSource<Address>>) user1 -> Observable.fromIterable(user.getAddresses()))
        .subscribe(address -> System.out.println(address.getStreet()));
复制代码

flatMap 对这些 Observable 发射的数据做的是合并(merge)操作,因此他们可能是交错的。还有一个操作符不会让变换后的 Observable 发射的数据交错,它严格按照顺序发射这些数据,这个操作符就是 concatMap。

2. groupBy

groupBy 操作符将一个 Observable 拆分为一些 Observable 集合,它们中的每一个都发射原始 Observable 的一个子序列。哪个数据项由哪一个 Observable 发射由函数判定的,这个函数给每一项一个指定的 key,key 相同的数据会被同一个 Observable 发射。 最终返回的是 Observable 的一个特殊子类 GroupedObservable。他是一个抽象类。getKey() 方法是 GroupedObservable 的方法,这个 Key 用于将数据分组到指定的 Observable。

3. buffer 和 window

  1. buffer 操作符 buffer 会定期收集Observable 数据并进行一个数据包裹,然后发射发射这些数据爆过,而不是一次发射一个值。buffer 操作符将一个 Observable 变化为另一个,原来的 Observable 正常发射数据,由变换产生的 Observable 发射这些数据的缓存集合。
Observable.range(0, 10)
        .buffer(2)
        .subscribe(integers -> System.out.println("onNext:" + integers),
                throwable -> System.out.println("onError:"),
                () -> System.out.println("onComplete:"));
复制代码

上述代码发射了从 0 到 10 这 10 个数字,由于使用了 buffer 操作符,他会将原先的 Observable 转换成新的 Observable,而新的 Observable 每次可发射两个数字,发射完毕后调用 OnComplete() 方法。 在 RxJava 中有许多 buffer 的重载方法,例如比较朝见的 buffer(count, skip)。buffer(count, skip) 从原始 Observable 的第一项数据开始创建新的缓存,此后每当收到 skip 项数据,就用 count 项数据填充缓存:开头的一项和后续的 count - 1 项。它以列表(List) 的形式发射缓存,这些缓存可能会有重叠部分(skip < count),也可能会有间隙(skip > count),取决于 skip 和 count 的值。

Observable.range(1, 11)
        .buffer(5, 1)
        .subscribe(integers -> System.out.println("onNext:" + integers),
                throwable -> System.out.println("onError:"),
                () -> System.out.println("onComplete:"));
复制代码

运行结果:

onNext:[1, 2, 3, 4, 5]
onNext:[2, 3, 4, 5, 6]
onNext:[3, 4, 5, 6, 7]
onNext:[4, 5, 6, 7, 8]
onNext:[5, 6, 7, 8, 9]
onNext:[6, 7, 8, 9, 10]
onNext:[7, 8, 9, 10, 11]
onNext:[8, 9, 10, 11]
onNext:[9, 10, 11]
onNext:[10, 11]
onNext:[11]
onComplete:
复制代码

如果原来的 Observable 发射了一个 onError 通知,那么 buffer 会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始 Observable 发射的数据。

  1. window 操作符 定期将来自原始 Observable 的数据分解为一个 Observable 窗口,发射这些窗口,而不是每次发射一项数据。window 发射的不是原始 Observable 的数据包,而是 Observables,这些 Observables 中的每一个都发射原始 Observable 数据的一个子集,最后发射一个 onComplete 通知。

4. first 和 last

  1. first 只发射第一项(或满足某个条件的第一项)数据。在 RxJava 2.0 中,使用 first() 需要一个默认的 Item,对于 Observable 而言,使用了 first() 会返回 Single 类型。
Observable.just(1, 2, 3)
        .first(2)
        .subscribe(integer -> System.out.println("Next: " + integer),
                (throwable) -> System.out.println("Error: " + throwable.getMessage()));
复制代码

如果 Observable 不发射任何数据,那么 first 操作符的默认值就会起作用。 在 RxJava 2.x 中,还有 firstElement 操作符表示只取第一个数据,没有默认值。firstOrError 操作符表示要么能去到第一个数据,要么执行 onError 方法,它们分别返回 Maybe 类型和 Single 类型。

  1. last 操作符 只发射最后一项(或满足某个条件的最后一项)数据。last 操作符跟 first 操作符类似,需要一个默认的 Item,也是返回single 类型,也同样拥有 lastElement 和 lastOrError 操作符。

5. take 和 takeLast

  1. take 操作符 只发射前面的 n 项数据,使用 take 操作符可以只修改 Observable 的行为,只返回前面的 n 项数据,发射完成通知,忽略剩余的数据。 如果对一个 Observable 使用 take(n)操作符,而那个 Observable 发射的数据少于 n 项,那么 take 操作符生成的 Observable 不会抛出异常或者发射 OnError 通知,而是仍然会发射那些数据。 take 有一个重载方法能够接受一个时长而不是数量参数。它会发射 Observable 开始的那段时间发射的数据,时间和时长单位通过参数设定。

  2. takeLast 操作符 发射 Observable 发射的最后 n 项数据,使用 takeLast 操作符修改原始 Observable,可以只发射 Observable 发射的最后 n 想数据,忽略前面的数据。同样,如果对一个 Observable 使用 takeLast(n) 操作符,而那个 Observable 发射的数据少于 n 想,那么 takeLast 操作符生成的 Observable 不会抛出异常或者发射 onError 通知,而是仍然发射那些数据。takeLast 也有一个重载方法能够接受一个时长takeLast(long time, TimeUnit unit),它会发射生命周期内最后一段时间发射的数据。

6. skip 和 skipLast

  1. skip 操作符 skip 跳过 Observable 发射的前 n 项数据,只保留之后的数据。skip 也有一个重载方法能够接受时长而不是数量参数skip(long time, TimeUnit unit)。它会丢弃原始 Observable 开始那段时间发射的数据,时长和时间单位通过参数指定。
  2. skipLast 操作符 skipLast 忽略 Observable 发射的后 n 项数据,只保留之前的数据。skipLast 同样有一个重载方法能够接受时长而不是数量参数。

7. elementAt 和 ignoreElements

  1. elementAt 操作符 只发射第 n 项数据,elementAt 操作符获取原始 Observable 发射的数据序列指定索引位置的数据项,然后当做自己的唯一数据发射。它传递一个基于 0 的索引值,发射原始 Observable 数据序列对应索引位置的值,如果传递给 elementAt 的值为 5,那么它会发射第 6 项数据。如果传递的是一个负数,则将会抛出一个 IndexOutOfBoundsExectption 异常,返回一个 Maybe 类型 如果原始 Observable 的数据项数小于 index + 1,那么会调用 onComplete() 方法(在 RxJava 1.x 中也会抛出一个 IndexOutOfBoundsExectption 异常)。所以,elementAt 还提供了一个带默认值的方法,它返回一个 Single 类型。
Observable.just(1, 2, 3, 4, 5)
        .elementAt(10, 0)
        .subscribe(integer -> System.out.println("Next: " + integer),
                throwable -> System.out.println("Error: " + throwable.getMessage()));
复制代码

如果 index 超出了索引范围,那么取默认值 0。跟 first、last 操作符类似,element 还有一个 elementAtOrError 操作符,表示要么能取到指定索引位置的数据,要么执行 onError 方法,也是返回 Single 类型。 2. ignoreElement ignoreElement 不发射任何数据,只发射 Observable 的终止通知,ignoreElement 操作符抑制原始 Observable 发射的所有数据,只允许它的终止通知(onComplete 或 onError) 通过。它返回一个 Completable 类型,它将确保永远不会调用被观察者的 onNext 方法。

8. distinct 和 filter

  1. distinct 操作符 过滤掉重复的数据项,distinct 的过滤规则是:只允许还没发射过的数据项通过。distinct 还能接受一个 Function 作为参数,这个函数根据原始 Observable 发射的数据项产生一个 key,然后比较这些 key 而不是数据本身,来判定两个数据是否不同。 与 distinct 类似的是 distinctUntilChanged 操作符,该操作符与 distinct 的区别是,它只判定一个数据和它的直接前驱是否不同。
  2. filter 操作符 只发射通过谓词测试的数据项,filter 操作符使用指定的一个谓词函数测试数据项,只有通过测试的数据才会被发射。

9. debounce

仅在过了一段指定的时间还没发射数据时才发射一个数据,debounce 操作符会过滤掉发射速率过快的数据项。debounce 还有另一种形式,即使用一个 Function 函数来限制发送的数据。 跟 debounce 类似的是 throttleWithTimeout 操作符,它与只使用时间参数来限流的 debounce 的功能相同。

转载于:https://juejin.im/post/5bc70e00e51d450e543ece52

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值