RxJava 2.x 使用详解(六) 变换操作符

2017-08-11  |   Android   android, reactive-streams, rxjava

回到顶部
  1. 前序
  2. Map
  3. flatMap
  4. flatMapIterable
  5. concatMap
  6. switchMap
  7. cast
  8. scan
  9. buffer
  10. toList
  11. groupBy
  12. toMap
  13. 尾声
  14. 相关文章

前序

  忙了一段时间后赶紧趁着空闲时间填一下坑,文章其实写了一段时间但是没有发布,最近校对下确保没有错误发出来。本期将介绍下RxJava的变换操作符,也是最后一期常用操作符的介绍。

Map

  基本的转换操作符,可以把每一个元素转换成新的元素发射,接收一个Function<T,R>作为转换逻辑的操作,下面是例子:

Flowable.just(1, 2, 3)
        .map(integer -> "int" + integer)
        .subscribe(ele -> Log.i("tag", String.valueOf(ele)));

  上述例子中map操作符返回了Flowable<String>,最终输出的结果为:int1、int2、int3。

flatMap

  上面的Map操作符是把每一个元素转换成一个新的元素,但是flatMap操作符是把每一个元素转换成新的被观察者,每个被观察者发射的元素将会合并成新的被观察者,这些元素顺序输出,例如下面的:

Flowable.just(1, 2, 3)
        .flatMap((Function<Integer, Publisher<?>>)
                integer -> Flowable.just("a",integer))
        .subscribe(ele -> Log.i("tag", String.valueOf(ele)));

  上述代码中把每一个just发射的元素转换成新的Flowable,而每一个新的Flowable额外添加一个“a”元素,所以上述的例子输出结果是:a、1、a、2、a、3。

flatMapIterable

  flatMapIterable与flatMap类似,但是flatMapIterable是把每一个元素转换成Iterable,例子如下:

Flowable.just(1, 2, 3)
        .flatMapIterable((Function<Integer, Iterable<?>>)
                integer -> Arrays.asList("a", integer))
        .subscribe(ele -> Log.i("tag", String.valueOf(ele)));

  上述代码把每一个元素转换成一个List,每个list以元素“a”开头,所以上述的例子输出结果是:a、1、a、2、a、3。

concatMap

  concatMap操作符合flatMap操作符类似,接收的参数和转换都是类似的,例子如下:

Flowable.just(1, 2, 3)
        .concatMap(integer -> Flowable.just("a", integer))
        .subscribe(ele -> Log.i("tag", String.valueOf(ele)));

  上述的例子输出结果是:a、1、a、2、a、3。flatMap操作符内部是使用merge合并元素,concatMap操作符则是通过concat合并元素,前者可能会出现元素交错问题,后者严格按照顺序发射。另外concatMap也有类似的concatMapIterable操作符,这里就不一样介绍了。

switchMap

  switchMap用法与flatMap类似,但是转换出来的每一个新的数据(被观察者)发射会取代掉前一个被观察者,如下例子:

Flowable.just(1, 2, 3)
        .switchMap(integer ->
                Flowable.timer(1, TimeUnit.SECONDS)
                        .map(longValue -> integer)
        )//延迟1s发送元素
        .subscribe(ele -> Log.i("tag", String.valueOf(ele)));

  上面的例子最终只会输出3这个元素,其他元素被覆盖替代掉不再发送。

cast

  强制转换每一个元素的类型,内部调用map操作符来进行转换:

Flowable.just(1, 2, 3)
        .cast(Number.class)
        .subscribe(ele -> Log.i("tag", String.valueOf(ele)));

  上述代码把每个元素都转换成Number类型,然后再发射。

scan

  扫描每一个元素,第一个元素将忽略,从第二个元素开始(可以获得上一个元素的值)进行变换后返回,例如:

Flowable.just(1, 2, 3)
        .scan((last, item) -> {
            Log.i("tag", "last:" + String.valueOf(last));
            Log.i("tag", "item:" + String.valueOf(item));
            return item+1;
        })
        .subscribe(ele -> Log.i("tag", String.valueOf(ele)));

  上述代码输出结果为1、3、4。

buffer

  buffer操作符是把多个元素打包成一个元素一次过发送数据,例如下面例子:

Flowable.just(1, 2, 3, 4, 5)
        .buffer(3)//三个元素打包成一个元素
        .subscribe(intList -> Log.i("tag", intList.toString()));

  上述代码把三个元素组合成一个List发送,输出结果为:[1, 2, 3]、[4, 5]。

toList

  把所有元素转换成一个List一次过发送出去,如下面例子:

Flowable.just(1, 2, 3, 4, 5)
        .toList()
        .subscribe(intList -> Log.i("tag", intList.toString()));

  上述代码输出[1, 2, 3, 4, 5]。除了toList操作符以外,还有toSortedList操作符,而且toSortedList操作符也支持自定义排序方式,这里就不展开了。

groupBy

  groupBy操作符通过Function接收每个数据的分组key,然后返回GroupedFlowable,使用者可以再订阅这个被观察者进行数据输出,由于使用lambda表达式可能加大理解难度,这里给出普通写法的例子:

Flowable.just(1, 2, 3, 4, 5)
        .groupBy(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                //这里的返回值是分组的key
                return integer > 2 ? "A组" : "B组";
            }
        })
        .subscribe(new Consumer<GroupedFlowable<String, Integer>>() {
            @Override
            public void accept(GroupedFlowable<String, Integer> groupedFlowable)
                    throws Exception {
                //订阅转换成GroupedFlowable
                groupedFlowable.subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        String key = groupedFlowable.getKey();
                        Log.i("tag", key + ":" + String.valueOf(integer));
                    }
                });
            }
        });

  上述代码将输出:“B组:1、B组:2、A组:3、A组:4、A组:5”,上述代码转换成lambda表达式为:

Flowable.just(1, 2, 3, 4, 5)
        .groupBy(integer -> integer > 2 ? "A组" : "B组")
        .subscribe(groupedFlowable ->
                groupedFlowable.subscribe(
                        integer -> Log.i("tag", groupedFlowable.getKey()
                                + ":" + String.valueOf(integer))
                ));

toMap

  熟悉了groupBy后,toMap也是类似的,可以通过自定义key、value转换成对应的map,如下例子:

Flowable.just(1, 2, 3, 4, 5)
        .toMap(integer -> "key" + integer)//第一个参数Function返回Map的key
        .subscribe(map -> Log.i("tag", map.toString()));

  上述代码输出:“{key5=5, key2=2, key4=4, key1=1, key3=3}”,另外toMap还可以支持自定义每个item对应的value值(传入第二个Function处理),这里就不一一介绍了。

尾声

  RxJava 2.x中基本常用的操作符到此也说得差不多了,虽然还有很多其他的操作符还没有解析,但是理解了这些,大部分场景都够用了,万变不离其宗,以后有不懂的操作符也可以自行学习了,系列文章接下来将介绍下RxJava处理错误的机制和Android上的应用。

相关文章

  RxJava 2.x 使用详解(一) 快速入门: https://maxwell-nc.github.io/android/rxjava2-1.html

  RxJava 2.x 使用详解(二) 创建操作符: https://maxwell-nc.github.io/android/rxjava2-2.html

  RxJava 2.x 使用详解(三) 过滤操作符: https://maxwell-nc.github.io/android/rxjava2-3.html

  RxJava 2.x 使用详解(四) 合并聚合操作符: https://maxwell-nc.github.io/android/rxjava2-4.html

  RxJava 2.x 使用详解(五) 条件操作符: https://maxwell-nc.github.io/android/rxjava2-5.html

  RxJava 2.x 使用详解(六) 变换操作符: https://maxwell-nc.github.io/android/rxjava2-6.html



原创文章,欢迎转载,请保留出处。有任何错误、疑问或者建议,欢迎指出。
请注明文章出自于:https://maxwell-nc.github.io/android/rxjava2-6.html

上一篇:RxJava 2.x 使用详解(五) 条件操作符