RxJava2之过滤操作符与组合操作符

234 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

过滤操作符

过滤操作符用于过滤和选择Observable发射的数据序列。

1.filter

filter操作符是对源Observable产生的结果自定义规则进行过滤,只有满足条件的才会提交给订阅者,我们用它可以轻松实现对null数据的过滤。

filter.png

Observable.range(0,20).filter(new Predicate<Integer>() {
    @Override
    public boolean test(Integer integer) throws Exception {
        return integer%5==0;
    }
}).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.i("TAG", "accept: "+integer);
    }
});

输出结果

 I/TAG: accept: 0
 I/TAG: accept: 5
 I/TAG: accept: 10
 I/TAG: accept: 15

2.elementAt

elementAt操作符用于返回指定位置的数据,其重载方法elementAt(long index, T defaultItem)可指定默认值。

elementAt.png

Observable.range(0, 5).elementAt(10, -1).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.i(TAG, "accept: " + integer);
    }
});
Observable.range(0, 5).elementAt(2).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.i(TAG, "accept: " + integer);
    }
});

输出结果为

 I/TAG: accept: -1
 I/TAG: accept: 2

3.distinct

distinct操作符可用于过滤重复元素,其重载方法distinct(Function<? super T, K> keySelector)可以指定重复规则

distyin8.png

User user1 = new User("张三丰",100);
User user2 = new User("张翠山",30);
User user3 = new User("张无极",18);
User user4 = new User("珠儿",15);
User user5 = new User("周芷若",16);
User user6 = new User("小昭",15);
User user7 = new User("白眉鹰王",100);
User user8 = new User("白眉鹰王",101);
User user9 = new User("白眉鹰王",102);
User user10 = new User("白眉鹰王",103);
Observable.just(user1,user2,user3,user4,user5,user6,user7,user8,user9,user10)
.distinct()
.subscribe(new Consumer<User>() {
    @Override
    public void accept(User user) throws Exception {
        Log.i(TAG, "accept: "+user);
    }
});
Log.i(TAG, "============distinct()============");
Observable.just(user1,user2,user3,user4,user5,user6,user7,user8,user9,user10)
.distinct(new Function<User, Integer>() {
    @Override
    public Integer apply(User user) throws Exception {
        return user.getAge();//指定age相同则视为重复
    }
}).subscribe(new Consumer<User>() {
    @Override
    public void accept(User user) throws Exception {
        Log.i(TAG, "accept: "+user.toString());
    }
});

输出结果

 I/TAG: accept: 张三丰 100I/TAG: accept: 张翠山 30I/TAG: accept: 张无极 18I/TAG: accept: 珠儿 15I/TAG: accept: 周芷若 16I/TAG: accept: 小昭 15I/TAG: accept: 白眉鹰王 100I/TAG: accept: 白眉鹰王 101I/TAG: accept: 白眉鹰王 102I/TAG: accept: 白眉鹰王 103I/TAG: ============distinct()============
 I/TAG: accept: 张三丰 100I/TAG: accept: 张翠山 30I/TAG: accept: 张无极 18I/TAG: accept: 珠儿 15I/TAG: accept: 周芷若 16I/TAG: accept: 白眉鹰王 101I/TAG: accept: 白眉鹰王 102I/TAG: accept: 白眉鹰王 103

4.take/takeLast

take操作符只取Observable发射的前几项,takeLast与之相反。

take.png

Observable.range(0, 6).take(3).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.i(TAG, "accept: "+integer);
    }
});

输出结果

 I/TAG: accept: 0
 I/TAG: accept: 1
 I/TAG: accept: 2

5.skip

skip操作符会过滤掉Observable发射的前几项,skipLast与之相反。 skip可以接受一个时长参数。它会丢弃原始Observable开始的那段时间发射的数据,时长和时间单位通过参数指定。

skip.png

Observable.range(0, 6).skip(3).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.i(TAG, "accept: "+integer);
    }
});

输出结果

 I/TAG: accept: 3
 I/TAG: accept: 4
 I/TAG: accept: 5

组合操作符可以将多个Observable转换成我们想要的Observable

组合操作符

1.startWith/startWithArray

startWithstartWithArray)操作符可以在源Observable发射的数据开头插上一些数据 image

Observable.just(3,4,5)
.startWithArray(0,1,2)//在3,4,5前边插入0,1,2
.subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.i(TAG, "accept: "+integer);
    }
});

输出结果如下

 I/TAG: accept: 0
 I/TAG: accept: 1
 I/TAG: accept: 2
 I/TAG: accept: 3
 I/TAG: accept: 4
 I/TAG: accept: 5

2.merge

merge操作符可以将多个Observable的输出合并在一个Observable中进行发射,merge可能会让发射的数据错乱。注意Observable中任何一个发射的onError都会立即传递给观察者,而且会终止合并后的Observableimage

Observable obs1 = Observable.just(1,2,3).subscribeOn(Schedulers.io());
Observable obs2 = Observable.just(4,5,6);
Observable.merge(obs1,obs2).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.i(TAG, "accept: "+integer);
    }
});

输出结果如下

 I/TAG: accept: 4
 I/TAG: accept: 5
 I/TAG: accept: 6
 I/TAG: accept: 1
 I/TAG: accept: 2
 I/TAG: accept: 3

3.concat

concat操作符与merge操错符类似,不过contact操作符严格按照顺序发射数据,前面的Observable没有发射完,是不会发射后面的数据的。 iamge

Observable obs1 = Observable.just(1,2,3).subscribeOn(Schedulers.io());
Observable obs2 = Observable.just(4,5,6);
Observable.concat(obs1,obs2).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) throws Exception {
        Log.i(TAG, "accept: "+integer);
    }
});

输出结果如下

 I/TAG: accept: 1
 I/TAG: accept: 2
 I/TAG: accept: 3
 I/TAG: accept: 4
 I/TAG: accept: 5
 I/TAG: accept: 6

4.zip

zip操作符可以将两个或者多个Observable发射的数据按顺序组合起来,然后根据指定的函数变换他们,并发射一个新值,每个数据都只能用一次。zip只发射与发射数据项最少的Observable一样多的数据。

zip.png

Observable obs1 = Observable.just(1,2,3,4).subscribeOn(Schedulers.io());
Observable obs2 = Observable.just("a","b","c");
Observable.zip(obs1, obs2, new BiFunction<Integer,String,String>() {

    @Override
    public String apply(Integer integer, String s) throws Exception {
        return integer+s;
    }
}).subscribe(new Consumer<String>() {
    @Override
    public void accept(String o) throws Exception {
        Log.i(TAG, "accept: "+o);
    }
});

输出结果如下

 I/TAG: accept: 1a
 I/TAG: accept: 2b
 I/TAG: accept: 3c

obs1发射了4个数据项,obs2发射了3个数据项,结果只输出了3个,所以zip最终组合的数据的数量由发射数据最少的Observable来决定。

5.combineLatest

combineLatest操作符与zip类似,只不过zip是当原始Observable都发射了数据才组合他们并发射,儿combineLatest是当原始Observable中任意一个发射了数据就开始组合他们最近发射的数据,然后发射这个组合值,所以使用combineLatest的前提是所有的Observable都发射过数据。 image

Observable obs1 =   Observable.interval(1000, TimeUnit.MILLISECONDS);
Observable obs2 =   Observable.interval(600, TimeUnit.MILLISECONDS);
Observable.combineLatest(obs1, obs2, new BiFunction<Long,Long,String>() {
    @Override
    public String apply(Long aLong, Long aLong2) throws Exception {
        return aLong+" "+aLong2;
    }
}).subscribe(new Consumer<String>() {
    @Override
    public void accept(String s) throws Exception {
        Log.i(TAG, "accept: "+s);
    }
});

输出结果如下

 I/TAG: accept: 0 0
 I/TAG: accept: 0 1
 I/TAG: accept: 1 2
 I/TAG: accept: 1 3
 I/TAG: accept: 2 3
 I/TAG: accept: 2 4