【从零学 RxJava】RxJava 3 —— 变换操作符、过滤操作符
前言
操作符是 RxJava 的重要组成部分,本章节解读 变换操作符、过滤操作符
版本
3.0.4
map
对 Observable 发射的每一项数据应用一个函数,进行变换操作(直接类比 Lambda 的 map
就好),该操作返回的是一个发射这些结果的 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));
});
}
// 结果:
小
01234
大
56789
对于 GroupedObservable 的使用:
getKey
方法用于方法对应的 Key,改 Key 在groupBy
逻辑中指定- 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
}
数据 a
和 A
经过 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
只发射通过 谓语函数 的数据项(类比于 Lambda 的 filter
)
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 实战 —— 沈哲