【Android TimeCat】 RxJava的使用(三)对象转换器——map、flatMap
map
在使用map
之前要先说道一个接口:Func1
,Func1
和上一篇提到的Action1
相似。Func1
和 Action
的区别在于, Func1
包装的是有返回值的方法。
接下来就是map的用法,看代码更直观点;
例:
得到多个Student对象中的name,保存到nameList中1
2
3
4
5
6
7
8
9
10
11
12
13
14
15Observable.just(student1, student2, student2)
//使用map进行转换,参数1:转换前的类型,参数2:转换后的类型
.map(new Func1<Student, String>() {
public String call(Student i) {
String name = i.getName();//获取Student对象中的name
return name;//返回name
}
})
.subscribe(new Action1<String>() {
public void call(String s) {
nameList.add(s);
}
});
可以看到Observable
中原来的参数是Student对象
,而最后我们需要的是name
,这里使用了map
来实现这一转换的过程。当然,map
可以多次使用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//多次使用map,想用几个用几个
Observable.just("Hello", "World")
.map(new Func1<String, Integer>() {//将String类型的转化为Integer类型的哈希码
public Integer call(String s) {
return s.hashCode();
}
})
.map(new Func1<Integer, String>() {//将转化后得到的Integer类型的哈希码再转化为String类型
public String call(Integer integer) {
return integer.intValue() + "";
}
})
.subscribe(new Action1<String>() {
public void call(String s) {
Log.i(TAG, s);
}
});
flatMap
flatMap
是一个比教难理解的一个转换,在这里先假设一个需求,需要打印多个Student
所学的课程。这跟之前获取Student
的name
又不同了,这里先确定一下关系,一个Student
类中只有一个name
,而一个Student
却有多门课程(Course),Student
我们可以理解成这样:1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* 学生类
*/
class Student {
private String name;//姓名
private List<Course> coursesList;//所修的课程
}
/**
* 课程类
*/
class Course {
private String name;//课程名
private String id;
}
如果使用map
来实现打印所有学生所修个课程名,实现的代码是这样的:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22List<Student> students = new ArrayList<Student>();
students.add...
...
Action1<List<Course>> action1 = new Action1<List<Course>>() {
public void call(List<Course> courses) {
//遍历courses,输出cuouses的name
for (int i = 0; i < courses.size(); i++){
Log.i(TAG, courses.get(i).getName());
}
}
};
Observable.from(students)
.map(new Func1<Student, List<Course>>() {
public List<Course> call(Student student) {
//返回coursesList
return student.getCoursesList();
}
})
.subscribe(action1);
可以看到,在Action1
中出现了for来循环打印课程名,使用RxJava
就是为了剔除这样的嵌套结构,使得整体的逻辑性更强。这时候就可以使用flatMap
了,使用flatMap
实现的代码是这样的:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17List<Student> students = new ArrayList<Student>();
students.add...
...
Observable.from(students)
.flatMap(new Func1<Student, Observable<Course>>() {
public Observable<Course> call(Student student) {
return Observable.from(student.getCoursesList());
}
})
.subscribe(new Action1<Course>() {
public void call(Course course) {
Log.i(TAG, course.getName());
}
});
这样就实现了跟上面代码一样的效果,看起来有点懵?确实,flatMap
理解起来有点绕,刚接触flatMap
的时候我也是懵逼一个。下面我将flatMap
的示意图,希望能帮助理解:
flatMap示意图
由上图可以看出Student1
、Student2
经过flatMap
后,按顺序依次经历了Observable1
、Observable2
,分别转化为Course
。最后按顺序得到Course1
、Course2
、Course3
、Course4
、Course5
、Course6
,其中1-3由Student1得到,4-6由Student2得到。
结合代码和示意图,是不是对flatMap有了一定的理解。
注意:FlatMap对这些Observables发射的数据做的是合并(merge)操作,因此它们可能是交错的。也就说,传入的顺序可能跟出来的顺序不一样。
如果要保证顺的的话,可以使用concatMap。
#其他操作符
除了map
和flatMap
之外,还有其他操作符以供使用。这里就不一一列举他们的用法了,其他常用的操作符如下:
filter
:集合进行过滤each
:遍历集合take
:取出集合中的前几个skip
:跳过前几个元素
参考
https://www.jianshu.com/p/52cd2d514528
http://gank.io/post/560e15be2dca930e00da1083