参考转载自https://www.jianshu.com/p/88779bda6691
初学者对于这两个操作符容易分不太清,本文总结一下。
Map
transform the items emitted by an Observable by applying a function to each item
意思是把Observable发射的每个item按照某个规则进行转换。
map()操作符就是用于变换Observable对象的,经过map操作符后返回一个Observable对象,这样就可以实现链式调用,在一个Observable对象上多次使用map操作符,最终将最简洁的数据传递给Subscriber对象。
图中map中的函数作用是将圆形事件转换为矩形事件, 从而导致下游接收到的事件就变为了矩形.用代码来表示这个例子就是:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
}).map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
return "This is result " + integer;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d(TAG, s);
}
});
在上游我们发送的是数字类型, 而在下游我们接收的是String类型, 中间起转换作用的就是map操作符, 运行结果为:
D/TAG: This is result 1
D/TAG: This is result 2
D/TAG: This is result 3
并且可以对一个Observable多次使用map:
//刚创建的Observable是String类型的
Observable.just("Hellp Map Operator")
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return 2015;//通过第一个map转成Integer
}
}).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
return String.valueOf(integer);//再通过第二个map转成String
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println(s);
}
});
FlatMap
flatMap是一个非常强大的操作符
transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable
FlatMap将一个发送事件的上游Observable变换为多个发送事件的Observables,然后将它们发射的事件合并后放进一个单独的Observable里.
这句话比较难以理解, 我们先通俗易懂的图片来详细的讲解一下, 首先先来看看整体的一个图片:
先看看上游, 上游发送了三个事件, 分别是1,2,3, 注意它们的颜色.
中间flatMap的作用是将圆形的事件转换为一个发送矩形事件和三角形事件的新的上游Observable.
还是不能理解? 别急, 再来看看分解动作:
上游每发送一个事件, flatMap都将创建一个新的水管, 然后发送转换之后的新的事件, 下游接收到的就是这些新的水管发送的数据. 这里需要注意的是, flatMap并不保证事件的顺序, 也就是图中所看到的, 并不是事件1就在事件2的前面. 如果需要保证顺序则需要使用concatMap
.
例子如下:
先加一个函数
static Observable<List<String>>query(){
List<String> s = Arrays.asList("Java", "Android", "Ruby", "Ios", "Swift");
return Observable.just(s);
}
我们打印所有query到的语言:
// 注意这里的参数是 query所返回的Observable的输出,并且返会一个Observable<String>
query().flatMap(new Func1<List<String>, Observable<String>>() {
@Override
public Observable<String> call(List<String> strings) {
//结合from处理
return Observable.from(strings);
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println("_flatMap:"+s);
}
});
日志:
_flatMap:Java
_flatMap:Android
_flatMap:Ruby
_flatMap:Ios
_flatMap:Swift
注意:query返回的Observable的输出是List<String>,在flatMap中变成了参数,而处理过后,返回一个Observable<String>.
假设这时候我们需要处理一下所获取的结果,我们加个前缀,在保证不修改subscribe的前提下我们可以这么做:
增加个函数,用来增加个前缀:
static Observable<String>addPre(String lan){
return Observable.just("addPre_"+lan);
}
代码可以这么写:
query().flatMap(new Func1<List<String>, Observable<String>>() {
@Override
public Observable<String> call(List<String> strings) {
return Observable.from(strings);
}
}).flatMap(new Func1<String, Observable<String>>() {
@Override
public Observable<String> call(String s) {
//我们在这里调用`addPre`方法,就行处理
return addPre(s);
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println(s);
}
});
输出日志:
addPre_Java
addPre_Android
addPre_Ruby
addPre_Ios
addPre_Swift
map与flatMap的区别(出自朱凯):
map 是在一个 item 被发射之后,到达 map 处经过转换变成另一个 item ,然后继续往下走;
flapMap 是 item 被发射之后,到达 flatMap 处经过转换变成一个 Observable ,而这个 Observable 并不会直接被发射出去,而是会立即被激活,然后把它发射出的每个 item 都传入流中,再继续走下去。
所以 flatMap 和 map 有两个区别:
- 经过 Observable 的转换,相当于重新开了一个异步的流;
- item 可以被分散,个数发生变化。
这个flatMap还是比较难以理解,它到底是如何工作的.
自己还需要多去了解一下.