RxJava2.x 之过滤操作符

目录结构

debounce

distinct

elementAt

filter

first

ignoreElements

last

sample

skip or skipLast

take or takeLast

debounce

此操作符会过滤掉发射速率过快的数据项。emmm这样来理解:此操作符需要传入一个时间单位,然后在此事件单位内发射的数据都会被过滤掉,不会传递到下游。看例子:

Observable.just(1, 2, 3, 4, 5, 6, 7)
                .debounce(1, TimeUnit.SECONDS)
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d("debounce", "onSubscribe");
                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d("debounce", "onNext: 接收的数据--> " + integer);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("debounce", "onError");
                    }

                    @Override
                    public void onComplete() {
                        Log.d("debounce", "onComplete");
                    }
                });
        /**
         * 04-09 14:20:24.866 14445-14445/com.example.testlink D/debounce: onSubscribe
         * 04-09 14:20:24.866 14445-14445/com.example.testlink D/debounce: onNext: 接收的数据--> 7
         * 04-09 14:20:24.866 14445-14445/com.example.testlink D/debounce: onComplete
         */
    }

 由最后的结果可以知道,数据源共有7个数据,但最终只接收的了最后一个数据。在一秒的时间内已经发射了前面6个数据,自然下游接收的数据就只有一个了。

distinct

过滤规则:只允许还没有发射过的数据项通过。简单说就是去重。基本数据的例子就不做示范,举个引用类型的数据来看是否也能够达到去重的效果:

        User user1 = new User("15");
        User user2 = new User("16");
        User user3 = new User("17");
        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user1);
        list.add(user2);
        list.add(user2);
        list.add(user3);
        list.add(user3);
        list.add(user3);
        
        Observable.fromIterable(list)
                .distinct()
                .subscribe(new Observer<User>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d("distinct", "onSubscribe: ");
                    }

                    @Override
                    public void onNext(User integer) {
                        Log.d("distinct", "onNext: " + integer.age);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("distinct", "onError: ");
                    }

                    @Override
                    public void onComplete() {
                        Log.d("distinct", "onComplete: ");
                    }
                });
        /**
         *04-09 17:16:31.456 25133-25133/com.example.testlink D/distinct: 
          onSubscribe:
         04-09 17:16:31.456 25133-25133/com.example.testlink D/distinct: onNext: 15
         04-09 17:16:31.456 25133-25133/com.example.testlink D/distinct: onNext: 16
         04-09 17:16:31.456 25133-25133/com.example.testlink D/distinct: onNext: 17
         04-09 17:16:31.456 25133-25133/com.example.testlink D/distinct: onComplete:
         */

创建了一个简单的User对象,有一个带一个age参数的构造方法,往list里加入重复对象。结果也只接收了3个不重复的对象。结论就是distinct 也能去重引用型数据。

elementAt

该操作符只选择发射数据序列中指定索引位置的数据来发射。并且只发射一次。索引位置从0开始。

Observable.just(1, 2, 3, 4, 5, 6)
                .elementAt(3)
                .subscribe(new MaybeObserver<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d("elementAt", "onSubscribe: ");

                    }

                    @Override
                    public void onSuccess(Integer integer) {
                        Log.d("elementAt", "onSuccess:  " + integer);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("onError", "onError: ");
                    }

                    @Override
                    public void onComplete() {
                        Log.d("onComplete", "onComplete: ");
                    }
                });
        /**
         *04-09 17:57:13.416 23283-23283/? D/elementAt: onSubscribe:
         04-09 17:57:13.416 23283-23283/? D/elementAt: onSuccess:  4
         */

 elementAt除了传入索引值外,还可以传入一个默认值。当发射序列索引值没有找到当前的索引值时就以默认值为数据发射。而如果不传入默认值时,也不会抛出越界异常,而是直接发射onComplete通知结束。

filter

字面意思很好理解,过滤掉不符合条件的数据。如下只发射大于3的数据出去。

       Observable.just(1, 2, 3, 4, 5, 6, 7)
                .filter(integer -> integer > 3)
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d("filter", "onSubscribe: ");
                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d("filter", "onNext: " + integer);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("filter", "onError: ");
                    }

                    @Override
                    public void onComplete() {
                        Log.d("filter", "onComplete: ");
                    }
                });
        /**
         * 04-09 14:22:53.576 16809-16809/com.example.testlink D/filter: onSubscribe:
         04-09 14:22:53.576 16809-16809/com.example.testlink D/filter: onNext: 4
         04-09 14:22:53.576 16809-16809/com.example.testlink D/filter: onNext: 5
         04-09 14:22:53.576 16809-16809/com.example.testlink D/filter: onNext: 6
         04-09 14:22:53.576 16809-16809/com.example.testlink D/filter: onNext: 7
         04-09 14:22:53.576 16809-16809/com.example.testlink D/filter: onComplete:
         */

first

只发射数据里的第一项数据。需要给定一个默认值。内层使用 elementAt 。

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Single<T> first(T defaultItem) {
    return elementAt(0L, defaultItem);
}

ignoreElements

不发射任何数据,只发射Observable的onComplete 通知。这里不做例子。

last

只发射最后一项数据,传入数据序列的索引值,需要给定默认索引值。这里不给出例子。

sample

发射在那段时间内的第一项数据。传入一个时间标记为采样单位,发射每过这个时间内的第一项数据。

 Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                e.onNext(1);
                Thread.sleep(1000);
                e.onNext(2);
                Thread.sleep(1000);
                e.onNext(3);
                Thread.sleep(1000);
                e.onNext(4);
                Thread.sleep(1000);
                e.onNext(5);
                Thread.sleep(1000);
                e.onNext(6);
            }
        })
                .sample(1000, TimeUnit.MILLISECONDS)
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d("sample", "onSubscribe: ");
                    }
                    @Override
                    public void onNext(Integer integer) {
                        Log.d("sample", "onNext: " + integer);
                    }
                    @Override
                    public void onError(Throwable e) {
                        Log.d("sample", "onError: ");
                    }
                    @Override
                    public void onComplete() {
                        Log.d("sample", "onComplete: ");
                    }
                });

这里来预期一下结果。每隔1秒采样一次,共有6个数据,并且刚好是发送完一个数据睡眠一秒。那么按照这个采样结果下游接收的数据应该就是所有的数据了。看结果

 04-10 16:55:33.866 26799-26799/com.example.testlink D/sample: onSubscribe: 
04-10 16:55:34.876 26799-26828/com.example.testlink D/sample: onNext: 1
04-10 16:55:35.876 26799-26828/com.example.testlink D/sample: onNext: 2
04-10 16:55:36.876 26799-26828/com.example.testlink D/sample: onNext: 3
04-10 16:55:37.876 26799-26828/com.example.testlink D/sample: onNext: 4
04-10 16:55:38.876 26799-26828/com.example.testlink D/sample: onNext: 5
04-10 16:55:39.876 26799-26828/com.example.testlink D/sample: onNext: 6

 正如预期一样的。那么将采样时间修改为3秒,那么预期结果应该只出现2个:

04-10 17:01:20.686 31055-31055/com.example.testlink D/sample: onSubscribe: 
04-10 17:01:23.686 31055-31089/com.example.testlink D/sample: onNext: 3
04-10 17:01:26.686 31055-31089/com.example.testlink D/sample: onNext: 6
 

完全如预期一样。

skip or skipLast

skip是跳过前面指定n项数据,最终发射后面的数据,skiplast是从倒序着来,跳过后面指定n项数据,发射前面的数据。另外skip跟skiplast还可以传入一个时间参数。意为只发射在当前单位时间内发射后或前的数据。传入时间单位就这样类似 debounce的效果。

take or takeLast

take 、takeLast 就是跟skip系列相反了。只发射指定n项前或者最后n项的数据。

发布了46 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/FooTyzZ/article/details/89145809