【从零学 RxJava】RxJava 3 —— 变换操作符、过滤操作符

前言

操作符是 RxJava 的重要组成部分,本章节解读 变换操作符过滤操作符

版本

3.0.4

map

Observable 发射的每一项数据应用一个函数,进行变换操作(直接类比 Lambdamap 就好),该操作返回的是一个发射这些结果的 Observable

demo

	static void map() {
        Observable.just("a", "b")
                .map(s -> s.toUpperCase())
                .subscribe(t -> System.out.println(t));
    }
	// A B

Observable 发射的字母被大写后,返回一个新的 Observable 发射这些消息

flatmap

将一个发射数据的 Observable 变换成多个 Observable,然后将他们发射的数据合并后放进一个单独的 Observable

demo

	static void flatmap() {
        Observable.just("a", "b")
                .flatMap(s -> Observable.just(s.toUpperCase()))
                .subscribe(t -> System.out.println(t));
    }
    // A B

Observable 发射的字母被转换为一个发射对应大写字母的 Observable,最后拼接成一个新的 Observable 返回

groupBy

将一个 Observable 拆分成 Observable 集合,返回 Observable 的子类 GroupedObservable,通过 Key 来分组对应的数据给对应的 Observable

demo

	static void groupBy() {
        Observable.range(0, 10)
                .groupBy(t -> t >= 5 ? "大" : "小")
                //.subscribeOn(Schedulers.trampoline())
                .subscribe(g -> {
                    System.out.println();
                    System.out.println(g.getKey());
                    g
                            //.subscribeOn(Schedulers.trampoline())
                            .subscribe(t -> System.out.print(t));
                });
    }

	// 结果:0123456789

对于 GroupedObservable 的使用:

  • getKey 方法用于方法对应的 Key,改 KeygroupBy 逻辑中指定
  • Key 对应的 GroupedObservable 则会发射对应的所有数据

buffer

缓存原 Observable 发射的数据,产生新的 Observable 发射缓存数据

demo

	static void buffer() {
        Observable.range(1, 10)
                .buffer(2)
                .subscribe(t -> System.out.println(t));
    }
    // 结果:
    [1, 2]
	[3, 4]
	[5, 6]
	[7, 8]
	[9, 10]

缓存容量为 2,缓存 Observable 发射的是 List

还有个重载方法 buffer(int count, int skip) 表示每次发射 count 条缓存数据,实际跳过 skip 条数据,看 demo 理解这句话

	static void buffer() {
        Observable.range(1, 10)
                .buffer(5, 1)
                .subscribe(t -> System.out.println(t));
    }
    // 结果:
    [1, 2, 3, 4, 5]
	[2, 3, 4, 5, 6]
	[3, 4, 5, 6, 7]
	[4, 5, 6, 7, 8]
	[5, 6, 7, 8, 9]
	[6, 7, 8, 9, 10]
	[7, 8, 9, 10]
	[8, 9, 10]
	[9, 10]
	[10]

比如,发射第一个缓存 List [1, 2, 3, 4, 5],则只跳过一条数据

window

缓存原 Observable 发射的数据,发射每一个缓存数据的 Observable,而不是发射每一项数据本身

demo

	static void window() {
        Observable.range(1, 10)
                .window(2)
                .subscribe(o -> {
                    o.subscribe(t -> System.out.print(t));
                    System.out.println("");
                    System.out.println("===============");
                });
    }
    // 结果:
    ===============
	12
	===============
	34
	===============
	56
	===============
	78
	===============
	910

first & last

比较好理解,只发射第一项(最后一项)数据,需要指定默认值

demo

	static void fal() {
        Observable.just(1, 2, 3)
                .first(0)
                .subscribe(t -> System.out.println(t));
        // 1

        Observable.empty()
                .last("default")
                .subscribe(t -> System.out.println(t));
        // default
    }

没有对应的值则发射指定的 默认值

take

使用 take 操作符可以只修改 Observable 的行为,返回前面几项数据,然后发射完成通知

demo

	static void take() throws InterruptedException {
        Observable.just(1, 2, 3)
                .take(2)
                .subscribe(t -> System.out.println(t));
    }
    // 1 2

还有一个重载方法 take(long time, TimeUnit unit) 可以返回指定时间发射的数据,示例 demo

	static void take() throws InterruptedException {
        Observable.interval(1, TimeUnit.SECONDS)
                .take(3, TimeUnit.SECONDS)
                .subscribe(t -> System.out.println(t));

        TimeUnit.SECONDS.sleep(5);
    }
    // 0 1 2

只发射前 3 秒的数据

takeLast

take 相反,发射后几条数据,同样有重载方法支持指定时间

demo

	static void takeLast() throws InterruptedException {
        Observable.just(1, 2, 3)
                .takeLast(2)
                .subscribe(t -> System.out.println(t));
        // 2 3

        Observable.intervalRange(0, 5, 1, 1, TimeUnit.SECONDS)
                .takeLast(3, TimeUnit.SECONDS)
                .subscribe(t -> System.out.println(t));

        TimeUnit.SECONDS.sleep(6);
        // 2 3 4
    }

skip

忽略 Observable 发射的前几项数据,只保留之后的数据,同样有重载方法支持跳过指定时间发射的数据

demo

	static void skip() throws InterruptedException {
        Observable.just(1, 2, 3)
                .skip(2)
                .subscribe(t -> System.out.println(t));
        // 3

        Observable.intervalRange(0, 5, 1, 1, TimeUnit.SECONDS)
                .skip(3, TimeUnit.SECONDS)
                .subscribe(t -> System.out.println(t));

        TimeUnit.SECONDS.sleep(5);
        // 3 4
    }

skipLast

skip 相对,忽略后几条发射的数据,同样有重载方法支持跳过最后指定时间发射的数据

demo

	static void skipLast() throws InterruptedException {
        Observable.just(1, 2, 3)
                .skipLast(2)
                .subscribe(t -> System.out.println(t));
        // 1

        Observable.intervalRange(0, 5, 1, 1, TimeUnit.SECONDS)
                .skipLast(3, TimeUnit.SECONDS)
                .subscribe(t -> System.out.println(t));

        TimeUnit.SECONDS.sleep(5);
        // 0 1
    }

elementAt

只发射指定位置的数据,elementAt 操作符获取原始 Observable 发射的数据序列指定索引位置的数据项,然后当作自己的唯一数据发射

传递参数负数,则会抛出异常,下标超出元素个数,默认调用 onComplete 方法,同时也提供重载方法 elementAt(long index, T defaultItem),在下标越界时返回 默认值

demo

	static void elementAt() {
        Observable.just(1, 2, 3)
                .elementAt(1)
                .subscribe(t -> System.out.println(t));
        // 2

        Observable.just(1, 2, 3)
                .elementAt(3, 0)
                .subscribe(t -> System.out.println(t));
        // 0
    }

下标从 0 开始,越界时返回指定的 默认值

ignoreElements

抑制原始 Observable 发射的所有数据,只允许它的终止通知(onError onComplete

demo

	static void ignoreElements() {
        Observable.just("test")
                .ignoreElements()
                .subscribe(
                       () -> System.out.println("complete")
                        , e -> System.out.println("error")
                );
    }
    // complete

distinct

过滤掉重复的数据项,还能接受一个 Function,可以根据原始数据生成一个 Key 来比较数据是否重复

demo

	static void distinct() {
        Observable.just("a", "a", "A")
                .distinct(s -> s.toUpperCase())
                .subscribe(t -> System.out.println(t));
        // a
    }

数据 aA 经过 Function 处理后 Key 相同,因此被认为是相同数据

distinctUntilChanged

distinct 的区别是,它只判定一个数据是否与前驱不同

demo

	static void distinctUntilChanged() {
        Observable.just(1, 2, 1, 1)
                .distinctUntilChanged()
                .subscribe(t -> System.out.println(t));
    }
    // 1 2 1

filter

只发射通过 谓语函数 的数据项(类比于 Lambdafilter

demo

	static void filter() {
        Observable.just(1, 2, 3)
                .filter(n -> n > 1)
                .subscribe(t -> System.out.println(t));
    }
    // 2 3

debounce

仅在过了一段指定时间还没发射数据时才发射一个数据

demo

	static void debounce() throws InterruptedException {
        Observable.create(e -> {
            if (!e.isDisposed()) {
                for (int i = 0; i < 5; i++) {
                    e.onNext(i);
                    TimeUnit.SECONDS.sleep(i);
                }
            }
        })
                .debounce(2, TimeUnit.SECONDS)
                .subscribe(t -> System.out.println(t));

        TimeUnit.SECONDS.sleep(30);
    }
    // 3 4

仅间隔时间超过 2s 的数据被发射

总结

本章节介绍了 RxJava变换操作符过滤操作符,之后的章节继续解读其他操作符

上一篇:【从零学 RxJava】RxJava 2 —— 创建操作符

下一篇:【从零学 RxJava】RxJava 4 —— 其他操作符

github

文中涉及的示例 demo

https://github.com/dangzhicairang/rxjava.git

参考

RxJava 2.x 实战 —— 沈哲

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值