RxJava2.x 变换操作符之 flatMap & concatMap
题图:Pixabay License
哈喽,朋友们,上一篇文章我们学习了 filter 操作符,今天我们来学习 RxJava 中比较重要的两个操作符 flatMap 和 concatMap。
1.flatMap
我们知道 flat 是平的意思,这个翻译还是有点生硬和抽象,我们还是不太理解,你就可以先理解成平铺的意思吧。
flatMap 是变换操作符的一种,它将一个发射数据的 Observable 变换为多个 Observable,然后将他们发射的数据合并后放入一个单独的 Observable。
举个简单的例子吧,假设上游有个数据源,数据源是学生对象的集合,学生有姓名和课程的属性,每个学生的课程可以有多个,需求是打印出所有学生的课程名称。
Student student1 = new Student();
List<Student.Course> list1 = new ArrayList<>();
list1.add(new Student.Course("语文1"));
list1.add(new Student.Course("数学1"));
list1.add(new Student.Course("英语1"));
list1.add(new Student.Course("物理1"));
list1.add(new Student.Course("化学1"));
student1.setName("张三");
student1.setCourses(list1);
Student student2 = new Student();
List<Student.Course> list2 = new ArrayList<>();
list2.add(new Student.Course("语文2"));
list2.add(new Student.Course("数学2"));
list2.add(new Student.Course("英语2"));
student2.setName("李四");
student2.setCourses(list2);
List<Student> studentList = new ArrayList<>();
studentList.add(student1);
studentList.add(student2);
Observable.just(studentList)
.flatMap((Function<List<Student>, ObservableSource<Student>>) students -> Observable.fromIterable(students))
.flatMap((Function<Student, ObservableSource<Student.Course>>) student -> {
LogUtil.i(TAG, "student name===" + student.getName());
return Observable.fromIterable(student.getCourses());
})
.subscribe(course -> LogUtil.i(TAG, "course===" + course.getCourseName()));
执行结果如下:
I/RxJavaOperatorActivity: student name===张三
I/RxJavaOperatorActivity: course===语文1
I/RxJavaOperatorActivity: course===数学1
I/RxJavaOperatorActivity: course===英语1
I/RxJavaOperatorActivity: course===物理1
I/RxJavaOperatorActivity: course===化学1
I/RxJavaOperatorActivity: student name===李四
I/RxJavaOperatorActivity: course===语文2
I/RxJavaOperatorActivity: course===数学2
I/RxJavaOperatorActivity: course===英语2
我们看到上面的代码没有 for 循环,却遍历打印了集合中的数据,RxJava 就是为了简化或者是取消 for 循环种方式,使用操作符来解决遍历循环的问题,从而是代码更加扁平化,使代码更加清晰和便于理解。
注意:flatMap 对这些 Observables 发射的数据做的是合并(merge)操作,因此它们可能是交错的,即不能保证数据的发射顺序。
2.concatMap
我们将上面的 flatMap 操作符换成 concatMap 操作符再看看打印的结果,修改代码如下:
Observable.just(studentList)
.concatMap((Function<List<Student>, ObservableSource<Student>>) students -> Observable.fromIterable(students))
.concatMap((Function<Student, ObservableSource<Student.Course>>) student -> {
LogUtil.i(TAG, "student name===" + student.getName());
return Observable.fromIterable(student.getCourses());
})
.subscribe(course -> LogUtil.i(TAG, "course===" + course.getCourseName()));
执行结果如下:
I/RxJavaOperatorActivity: student name===张三
I/RxJavaOperatorActivity: course===语文1
I/RxJavaOperatorActivity: course===数学1
I/RxJavaOperatorActivity: course===英语1
I/RxJavaOperatorActivity: course===物理1
I/RxJavaOperatorActivity: course===化学1
I/RxJavaOperatorActivity: student name===李四
I/RxJavaOperatorActivity: course===语文2
I/RxJavaOperatorActivity: course===数学2
I/RxJavaOperatorActivity: course===英语2
我们看到和 flatMap 的执行结果是一样的,我们发现打印的结果也是按照添加数据的顺序打印出来了,理论上 flatMap 执行的结果可能会有交错,原因是我们添加的数据过少,因此它们执行的时间也是差不多的,所以提现不出交错的情况。
好了,今天的学习内容就算完成了,感觉是不是非常简单?其实有时候你光看,理解起来是很慢的,但是你动手敲一遍立马就明白了,所以代码这个东西还是得多敲!
最后,我这边建了一个技术交流群,需要的朋友可以扫描下面的二维码加我微信并备注「加群」,拉你进入技术交流群!
飞哥带你去装逼,一直装逼到天黑!
另外,我还建了一个免费的知识星球用于学习交流,感兴趣的可以使用微信扫码加入哦!