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

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

回到顶部

前序

  忙了一段时间后赶紧趁着空闲时间填一下坑,文章其实写了一段时间但是没有发布,最近校对下确保没有错误发出来。本期将介绍下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 使用详解(五) 条件操作符