【Android】RxJava的使用(三)转换——map、flatMap

前两篇Android RxJava的使用(一)基本用法Android RxJava的使用(二)Action介绍了RxJava的基本用法,对Rxjava还不了解的请先看以上两篇。这篇为大家讲解RxJava中map和flatMap的使用。

参考:给 Android 开发者的 RxJava 详解 (本文部分内容引用自该博客)

回顾

前两篇为大家介绍了使用RxJava打印多个字符串的方法

     Observable.just("Hellow", "Wrold").subscribe(new Action1<String>() {
          @Override
          public void call(String s) {
              Log.i(TAG, s);
          }
      });

这样的例子基本没有实际用处,只是为大家演示如何使用Rxjava。今天就抛开这个例子。

map

在使用map之前要先说道一个接口:Func1,Func1和上一篇提到的Action1相似。Func1 和 Action的区别在于, Func1 包装的是有返回值的方法。 接下来就是map的用法,看代码更直观点; 例:得到多个Student对象中的name,保存到nameList中

        Observable.just(student1, student2, student2)
                //使用map进行转换,参数1:转换前的类型,参数2:转换后的类型
                .map(new Func1<Student, String>() {
                    @Override
                    public String call(Student i) {
                        String name = i.getName();//获取Student对象中的name
                        return name;//返回name
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        nameList.add(s);
                    }
                });

可以看到Observable中原来的参数是Student对象,而最后我们需要的是name,这里使用了map来实现这一转换的过程。当然,map可以多次使用。

        //多次使用map,想用几个用几个
        Observable.just("Hello", "World")
                .map(new Func1<String, Integer>() {//将String类型的转化为Integer类型的哈希码
                    @Override
                    public Integer call(String s) {
                        return s.hashCode();
                    }
                })
                .map(new Func1<Integer, String>() {//将转化后得到的Integer类型的哈希码再转化为String类型
                    @Override
                    public String call(Integer integer) {
                        return integer.intValue() + "";
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.i(TAG, s);
                    }
                });

flatMap

flatMap是一个比教难理解的一个转换,在这里先假设一个需求,需要打印多个Student所学的课程。这跟之前获取Student的name又不同了,这里先确定一下关系,一个Student类中只有一个name,而一个Student却有多门课程(Course),Student我们可以理解成这样:

    /**
     * 学生类
     */
    class Student {
        private String name;//姓名
        private List<Course> coursesList;//所修的课程
        ...
    }
    /**
     * 课程类
     */
    class  Course {
        private String name;//课程名
        private String id;
        ...
    }

如果使用map来实现打印所有学生所修个课程名,实现的代码是这样的:

        List<Student> students = new ArrayList<Student>();
        students.add...
        ...

        Action1<List<Course>> action1 = new Action1<List<Course>>() {
            @Override
            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>>() {
                    @Override
                    public List<Course> call(Student student) {
                        //返回coursesList
                        return student.getCoursesList();
                    }
                })
                .subscribe(action1);

可以看到,在Action1中出现了for来循环打印课程名,使用RxJava就是为了剔除这样的嵌套结构,使得整体的逻辑性更强。这时候就可以使用flatMap了,使用flatMap实现的代码是这样的:

        List<Student> students = new ArrayList<Student>();
        students.add...
        ...

        Observable.from(students)
                .flatMap(new Func1<Student, Observable<Course>>() {
                    @Override
                    public Observable<Course> call(Student student) {
                        return Observable.from(student.getCoursesList());
                    }
                })
                .subscribe(new Action1<Course>() {
                    @Override
                    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:跳过前几个元素

更多操作符

小结

看完map、flatMap后,慢慢能看到RxJava的实际用处了。不过只是这点功能的RxJava是远远不能满足我们的需求,更多的用法我只能在后面更新了。今天就到这里吧!!!

以上有错误之处感谢指出

更多: Android RxJava的使用(四)线程控制 —— Scheduler

参考:给 Android 开发者的 RxJava 详解 (本文部分内容引用自该博客)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏史上最简单的Spring Cloud教程

一篇RxJava友好的文章(三)

组合操作符 继上一篇讲述了过滤操作符,这一篇讲述组合操作符,组合操作符可用于组合多个Observable。组合操作符相对于过滤操作符要复杂很多,也较难以理解,需...

3655
来自专栏Golang语言社区

Go语言interface详解

interface Go语言里面设计最精妙的应该算interface,它让面向对象,内容组织实现非常的方便,当你看完这一章,你就会被interface的巧妙设计...

3719
来自专栏芋道源码1024

排序算法总结(多图)

不稳定的排序: 稳定性一个形象的比喻,本来有两个并列第三,一排序把原来并列的顺序给变了。 比如:选择排序、快速排序、堆排序、希尔排序; 参考链接

913
来自专栏逸鹏说道

Python3 与 C# 面向对象之~封装

原文:https://www.cnblogs.com/dotnetcrazy/p/9202988.html

2383
来自专栏机器学习入门

POJ 刷题系列:2159. Ancient Cipher

POJ 刷题系列:2159. Ancient Cipher 传送门:POJ 2159. Ancient Cipher 题意: 给定两个长度相等的字符串a, b...

2226
来自专栏Python

python2/3中 将base64数据写成图片,并将图片数据转为16进制数据的方法、bytes/string的区别

python 3中最重要的新特性可能就是将文本(text)和二进制数据做了更清晰的区分。文本总是用unicode进行编码,以str类型表示;而二进制数据以byt...

4392
来自专栏大闲人柴毛毛

JavaScript奇淫技巧(一)

if-else简化写法 代码中若出现多层if-else嵌套,代码就会显得臃肿不堪,这时可采用替代方案来浓缩代码。 常规写法:(臃肿不堪) if(){ ...

3606
来自专栏java工会

java枚举使用详解

2515
来自专栏逸鹏说道

Python3 与 C# 面向对象之~封装

在线编程:https://mybinder.org/v2/gh/lotapp/BaseCode/master 在线预览:http://github.lessch...

1683
来自专栏大数据钻研

44 个 JavaScript 变态题解析

当初笔者做这套题的时候不仅怀疑智商, 连人生都开始怀疑了…. 不过, 对于基础知识的理解是深入编程的前提. 让我们一起来看看这些变态题到底变态不变态吧! 第1题...

3496

扫码关注云+社区

领取腾讯云代金券