操作符Map分三种,一是我们通俗的Map;二是事件拆分再合并的强大无序操作符FlatMap;三是事件拆分再合并的强大有序操作符ConcatMap。
一、通俗的Map:起到事件类型的转换作用
具体如下:
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("01");
e.onNext("05");
e.onNext("08");
e.onNext("10");
e.onNext("16");
}
}).map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
logTag(s);
return Integer.parseInt(s.trim());
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
newValue = new Integer(integer).intValue();
logTag("newValue ===" + newValue);
logTag("oldValue ===" + oldValue);
logTag("logTag: newValue ÷ oldValue ===" + (float) newValue / (float) oldValue);
oldValue = newValue;
}
});
理解:
上游通过new ObservableOnSubscribe发送String型的事件,我们在中间通过map操作符,将String型事件转换为Interger事件:
map(new Function<String, Integer>());
上面Function中,前面String对应上游的原始发送事件,后面的Integer对应转换后的事件。
运行结果如下:
logTag: string===01
logTag: string===newValue ===1
logTag: string===oldValue ===1
logTag: string===logTag: newValue ÷ oldValue ===1.0
logTag: string===05
logTag: string===newValue ===5
logTag: string===oldValue ===1
logTag: string===logTag: newValue ÷ oldValue ===5.0
logTag: string===08
logTag: string===newValue ===8
logTag: string===oldValue ===5
logTag: string===logTag: newValue ÷ oldValue ===1.6
logTag: string===10
logTag: string===newValue ===10
logTag: string===oldValue ===8
logTag: string===logTag: newValue ÷ oldValue ===1.25
logTag: string===16
logTag: string===newValue ===16
logTag: string===oldValue ===10
logTag: string===logTag: newValue ÷ oldValue ===1.6
通过Map, 可以将上游发来的事件转换为任意的类型, 可以是一个Object, 也可以是一个集合,也可以是你想要的其他类型。
二、无序FlatMap
flatMap是一个非常强大的操作符,它将一个发送事件的上游Observable变换为多个发送事件的Observables,然后将它们发射的事件合并后放进一个单独的Observable里。这句话比较难以理解,我们通俗易懂的图片(该图借用简书上的以为大神Season_zlc的图片)来详细的讲解一下:
上游每发送一个事件, flatMap都将创建一个新的水管, 然后发送转换之后的新的事件, 下游接收到的就是这些新的水管发送的数据. 这里需要注意的是, flatMap并不保证事件的顺序, 也就是图中所看到的, 并不是事件1就在事件2的前面,所以叫做无序FlatMap。
用法如下:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
e.onNext(3);
e.onNext(4);
}
}).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
final List<String> list = new ArrayList<>();
for (int i = 0; i < 2; i++) {
list.add(integer + "");
}
return Observable.fromIterable(list).delay(16, TimeUnit.MILLISECONDS);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
logTag("subscribe→→→accept" + s);
}
});
flatMap将上游发来的每个事件转换为一个新的发送2(我们的for循环为2,所以是2个,如果我们要更多个的话,我们在for循环哪里修改即可)个String事件的水管, 为了看到flatMap结果是无序的,我们加了10毫秒的延时, 运行结果如下:
logTag: string===subscribe→→→accept1
logTag: string===subscribe→→→accept3
logTag: string===subscribe→→→accept3
logTag: string===subscribe→→→accept4
logTag: string===subscribe→→→accept4
logTag: string===subscribe→→→accept1
logTag: string===subscribe→→→accept2
logTag: string===subscribe→→→accept2
上面的结果确实是无序的。另外,我们要将原来的旧事件转换为几个新的世界,在flatMap下的for循环里面指定即可。
三、有序concatMap
它的作用和flatMap一模一样,不同的是,它输出的事件是严格按照上游发送过来的顺序来的。
还是上面flatMap的代码,将flatMap改为concatMap。其他的一概不动。运行结果如下:
logTag: string===subscribe→→→accept1
logTag: string===subscribe→→→accept1
logTag: string===subscribe→→→accept2
logTag: string===subscribe→→→accept2
logTag: string===subscribe→→→accept3
logTag: string===subscribe→→→accept3
logTag: string===subscribe→→→accept4
logTag: string===subscribe→→→accept4
Map操作符就这么多内容。今天下班,明天继续。