前面一篇文章中我们介绍了转换类操作符,那么这一章我们就来介绍下过滤类的操作符。顾名思义,这类operators主要用于对事件数据的筛选过滤,只返回满足我们条件的数据。过滤类操作符主要包含: Filter Take TakeLast TakeUntil Skip SkipLast ElementAt Debounce Distinct DistinctUntilChanged First Last等等。

Filter

filter(Func1)用来过滤观测序列中我们不想要的值,只返回满足条件的值,我们看下原理图:

还是拿前面文章中的小区Community[] communities来举例,假设我需要赛选出所有房源数大于10个的小区,我们可以这样实现:

  1. Observable.from(communities)
  2. .filter(new Func1<Community, Boolean>() {
  3. @Override
  4. public Boolean call(Community community) {
  5. return community.houses.size()>10;
  6. }
  7. }).subscribe(new Action1<Community>() {
  8. @Override
  9. public void call(Community community) {
  10. System.out.println(community.name);
  11. }
  12. });

Take

take(int)用一个整数n作为一个参数,从原始的序列中发射前n个元素.

现在我们需要取小区列表communities中的前10个小区

  1. Observable.from(communities)
  2. .take(10)
  3. .subscribe(new Action1<Community>() {
  4. @Override
  5. public void call(Community community) {
  6. System.out.println(community.name);
  7. }
  8. });

TakeLast

takeLast(int)同样用一个整数n作为参数,只不过它发射的是观测序列中后n个元素。

获取小区列表communities中的后3个小区

  1. Observable.from(communities)
  2. .takeLast(3)
  3. .subscribe(new Action1<Community>() {
  4. @Override
  5. public void call(Community community) {
  6. System.out.println(community.name);
  7. }
  8. });

TakeUntil

takeUntil(Observable)订阅并开始发射原始Observable,同时监视我们提供的第二个Observable。如果第二个Observable发射了一项数据或者发射了一个终止通知,takeUntil()返回的Observable会停止发射原始Observable并终止。

  1. Observable<Long> observableA = Observable.interval(300, TimeUnit.MILLISECONDS);
  2. Observable<Long> observableB = Observable.interval(800, TimeUnit.MILLISECONDS);
  3. observableA.takeUntil(observableB)
  4. .subscribe(new Subscriber<Long>() {
  5. @Override
  6. public void onCompleted() {
  7. System.exit(0);
  8. }
  9. @Override
  10. public void onError(Throwable e) {
  11. }
  12. @Override
  13. public void onNext(Long aLong) {
  14. System.out.println(aLong);
  15. }
  16. });
  17. try {
  18. Thread.sleep(Integer.MAX_VALUE);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }

程序输出:

  1. 0
  2. 1

takeUntil(Func1)通过Func1中的call方法来判断是否需要终止发射数据。

  1. Observable.just(1, 2, 3, 4, 5, 6, 7)
  2. .takeUntil(new Func1<Integer, Boolean>() {
  3. @Override
  4. public Boolean call(Integer integer) {
  5. return integer >= 5;
  6. }
  7. }).subscribe(new Action1<Integer>() {
  8. @Override
  9. public void call(Integer integer) {
  10. System.out.println(integer);
  11. }
  12. });

程序输出:

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5

Skip

skip(int)让我们可以忽略Observable发射的前n项数据。

过滤掉小区列表communities中的前5个小区

  1. Observable.from(communities)
  2. .skip(5)
  3. .subscribe(new Action1<Community>() {
  4. @Override
  5. public void call(Community community) {
  6. System.out.println(community.name);
  7. }
  8. });

SkipLast

skipLast(int)忽略Observable发射的后n项数据。

ElementAt

elementAt(int)用来获取元素Observable发射的事件序列中的第n项数据,并当做唯一的数据发射出去。

Debounce

debounce(long, TimeUnit)过滤掉了由Observable发射的速率过快的数据;如果在一个指定的时间间隔过去了仍旧没有发射一个,那么它将发射最后的那个。通常我们用来结合RxBing(Jake Wharton大神使用RxJava封装的Android UI组件)使用,防止button重复点击。

debounce(Func1)可以根据Func1的call方法中的函数来过滤,Func1中的中的call方法返回了一个临时的Observable,如果原始的Observable在发射一个新的数据时,上一个数据根据Func1的call方法生成的临时Observable还没结束,那么上一个数据就会被过滤掉。

Distinct

distinct()的过滤规则是只允许还没有发射过的数据通过,所有重复的数据项都只会发射一次。

过滤掉一段数字中的重复项:

  1. Observable.just(2, 1, 2, 2, 3, 4, 3, 4, 5, 5)
  2. .distinct()
  3. .subscribe(new Action1<Integer>() {
  4. @Override
  5. public void call(Integer i) {
  6. System.out.print(i + " ");
  7. }
  8. });

程序输出:

  1. 2 1 3 4 5

distinct(Func1)参数中的Func1中的call方法会根据Observable发射的值生成一个Key,然后比较这个key来判断两个数据是不是相同;如果判定为重复则会和distinct()一样过滤掉重复的数据项。

假设我们要过滤掉一堆房源中小区名重复的小区:

  1. List<House> houses = new ArrayList<>();
  2. //House构造函数中的第一个参数为该房源所属小区名,第二个参数为房源描述
  3. List<House> houses = new ArrayList<>();
  4. houses.add(new House("中粮·海景壹号", "中粮海景壹号新出大平层!总价4500W起"));
  5. houses.add(new House("竹园新村", "满五唯一,黄金地段"));
  6. houses.add(new House("竹园新村", "一楼自带小花园"));
  7. houses.add(new House("中粮·海景壹号", "毗邻汤臣一品"));
  8. houses.add(new House("中粮·海景壹号", "顶级住宅,给您总统般尊贵体验"));
  9. houses.add(new House("竹园新村", "顶层户型,两室一厅"));
  10. houses.add(new House("中粮·海景壹号", "南北通透,豪华五房"));
  11. Observable.from(houses)
  12. .distinct(new Func1<House, String>() {
  13. @Override
  14. public String call(House house) {
  15. return house.communityName;
  16. }
  17. }).subscribe(new Action1<House>() {
  18. @Override
  19. public void call(House house) {
  20. System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
  21. }
  22. });

程序输出:

  1. 小区:中粮·海景壹号; 房源描述:中粮海景壹号新出大平层!总价4500W
  2. 小区:竹园新村; 房源描述:满五唯一,黄金地段

DistinctUntilChanged

distinctUntilChanged()distinct()类似,只不过它判定的是Observable发射的当前数据项和前一个数据项是否相同。

同样还是上面过滤数字的例子:

  1. Observable.just(2, 1, 2, 2, 3, 4, 3, 4, 5, 5)
  2. .distinctUntilChanged()
  3. .subscribe(new Action1<Integer>() {
  4. @Override
  5. public void call(Integer i) {
  6. System.out.print(i + " ");
  7. }
  8. });

程序输出:

  1. 2 1 2 3 4 3 4 5

distinctUntilChanged(Func1)distinct(Func1)一样,根据Func1中call方法产生一个Key来判断两个相邻的数据项是否相同。

我们还是拿前面的http://ocjtywvav.bkt.clouddn.com/rxjava/operator/filter/过滤房源的例子:

  1. Observable.from(houses)
  2. .distinctUntilChanged(new Func1<House, String>() {
  3. @Override
  4. public String call(House house) {
  5. return house.communityName;
  6. }
  7. }).subscribe(new Action1<House>() {
  8. @Override
  9. public void call(House house) {
  10. System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
  11. }
  12. });

程序输出:

  1. 小区:中粮·海景壹号; 房源描述:中粮海景壹号新出大平层!总价4500W
  2. 小区:竹园新村; 房源描述:满五唯一,黄金地段
  3. 小区:中粮·海景壹号; 房源描述:毗邻汤臣一品
  4. 小区:竹园新村; 房源描述:顶层户型,两室一厅
  5. 小区:中粮·海景壹号; 房源描述:南北通透,豪华五房

First

first()顾名思义,它是的Observable只发送观测序列中的第一个数据项。

获取房源列表houses中的第一套房源:

  1. Observable.from(houses)
  2. .first()
  3. .subscribe(new Action1<House>() {
  4. @Override
  5. public void call(House house) {
  6. System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
  7. }
  8. });

程序输出:

  1. 小区:中粮·海景壹号; 房源描述:中粮海景壹号新出大平层!总价4500W

first(Func1)只发送符合条件的第一个数据项。

现在我们要获取房源列表houses中小区名为竹园新村的第一套房源。

  1. Observable.from(houses)
  2. .first(new Func1<House, Boolean>() {
  3. @Override
  4. public Boolean call(House house) {
  5. return "竹园新村".equals(house.communityName);
  6. }
  7. })
  8. .subscribe(new Action1<House>() {
  9. @Override
  10. public void call(House house) {
  11. System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
  12. }
  13. });

程序输出:

  1. 小区:竹园新村; 房源描述:满五唯一,黄金地段

Last

last()只发射观测序列中的最后一个数据项。

获取房源列表中的最后一套房源:

  1. Observable.from(houses)
  2. .last()
  3. .subscribe(new Action1<House>() {
  4. @Override
  5. public void call(House house) {
  6. System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
  7. }
  8. });

程序输出:

  1. 小区:中粮·海景壹号; 房源描述:南北通透,豪华五房

last(Func1)只发射观测序列中符合条件的最后一个数据项。

获取房源列表houses中小区名为竹园新村的最后一套房源:

  1. Observable.from(houses)
  2. .last(new Func1<House, Boolean>() {
  3. @Override
  4. public Boolean call(House house) {
  5. return "竹园新村".equals(house.communityName);
  6. }
  7. })
  8. .subscribe(new Action1<House>() {
  9. @Override
  10. public void call(House house) {
  11. System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
  12. }
  13. });

程序输出:

  1. 小区:竹园新村; 房源描述:顶层户型,两室一厅

这一章我们就先聊到这,更多的过滤类操作符的介绍大家可以去查阅官方文档和源码;在下一章我们将继续介绍组合类操作符。

如果你喜欢我的文章,就关注下我的知乎专栏或者在 GitHub 上添个 Star 吧!

RxJava系列4(过滤操作符)的更多相关文章

  1. RxJava系列5(组合操作符)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  2. RxJava系列3(转换操作符)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  3. RxJava系列番外篇:一个RxJava解决复杂业务逻辑的案例

    之前写过一系列RxJava的文章,也承诺过会尽快有RxJava2的介绍.无奈实际项目中还未真正的使用RxJava2,不敢妄动笔墨.所以这次还是给大家分享一个使用RxJava1解决问题的案例,希望对大家 ...

  4. RxJava系列7(最佳实践)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  5. RxJava系列6(从微观角度解读RxJava源码)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  6. RxJava系列2(基本概念及使用介绍)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  7. RxJava系列1(简介)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  8. RxJava系列之二 变换类操作符具体解释1

    1.回想 上一篇文章我们主要介绍了RxJava , RxJava 的Observables和 RxJava的just操作符.以及RxJava一些经常使用的操作. 没看过的抓紧点我去看吧. 事实上RxJ ...

  9. RxJava2实战---第五章 变换操作符和过滤操作符

    RxJava2实战---第五章 变换操作符和过滤操作符 RxJava的变换操作符主要包括以下几种: map():对序列的每一项都用一个函数来变换Observable发射的数据序列. flatMap() ...

随机推荐

  1. leetCode:206 反转链表

    206. 反转链表 题目:反转一个单链表. 进阶:链表可以迭代或递归地反转.你能否两个都实现一遍? 非递归代码: class Solution { public ListNode reverseLis ...

  2. 用golang 实现一个代理池

    背景 写爬虫的时候总会遇到爬取速度过快而被封IP的情况,这个时候就需要使用代理了.在https://github.com/henson/ProxyPool 的启发下,决定自己实现一个代理池.项目已经开 ...

  3. POJ1331 Multiply(strtol函数练习)

    题目链接:http://poj.org/problem?id=1331 主要介绍strtol函数: long int strtol(const char *nptr,char **endptr,int ...

  4. 简洁明了的插值音频重采样算法例子 (附完整C代码)

    近一段时间在图像算法以及音频算法之间来回游走. 经常有一些需求,需要将音频进行采样转码处理. 现有的知名开源库,诸如: webrtc , sox等, 代码阅读起来实在闹心. 而音频重采样其实也就是插值 ...

  5. 关于换了手机后,导致原来连的fiddler抓不到新手机上的包的解决方法

    原来我们测试都是一台安卓机,一台ios机,由于机子不够,所以安卓机都是自己的手机,可以连内网,也可以连外网 但是最近这几天,不知道公司抽了什么风.把网都给限制了,只有公司的测试机,才能连内网测,结果我 ...

  6. Android实用代码七段(三)

    正文  一.获取已经安装APK的路径 PackageManager pm = getPackageManager(); for (ApplicationInfo app : pm.getInstall ...

  7. 大数据hadoop面试题2018年最新版(美团)

    还在用着以前的大数据Hadoop面试题去美团面试吗?互联网发展迅速的今天,如果不及时更新自己的技术库那如何才能在众多的竞争者中脱颖而出呢? 奉行着"吃喝玩乐全都有"和"美 ...

  8. HTTP协议----URI,URL,持久连接,管道与Cookie

    URI与URL有什么不同呢? URI:Universal Resource Identifier统一资源标志符 URL:Universal Resource Locator统一资源定位器 URI是用来 ...

  9. "机器人防火墙":人机识别在应用安全及风控领域的一点实践

    美剧 WestWorld 第二集里有个场景十分有意思:游客来到西部世界公园,遇到了一个漂亮的女接待员,但无法区分对方是否是人类,于是产生了如下对话: Guest: "Are you real ...

  10. java冒泡排序和快速排序

    本ID技术干货公众号"java工会",欢迎关注指正. 一.冒泡排序 1.算法介绍 设排序表长为n,从后向前或者从前向后两两比较相邻元素的值,如果两者的相对次序不对(A[i-1] & ...