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

Filter

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

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

Observable.from(communities)
.filter(new Func1<Community, Boolean>() {
@Override
public Boolean call(Community community) {
return community.houses.size()>10;
}
}).subscribe(new Action1<Community>() {
@Override
public void call(Community community) {
System.out.println(community.name);
}
});

Take

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

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

Observable.from(communities)
.take(10)
.subscribe(new Action1<Community>() {
@Override
public void call(Community community) {
System.out.println(community.name);
}
});

TakeLast

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

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

Observable.from(communities)
.takeLast(3)
.subscribe(new Action1<Community>() {
@Override
public void call(Community community) {
System.out.println(community.name);
}
});

TakeUntil

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

Observable<Long> observableA = Observable.interval(300, TimeUnit.MILLISECONDS);
Observable<Long> observableB = Observable.interval(800, TimeUnit.MILLISECONDS); observableA.takeUntil(observableB)
.subscribe(new Subscriber<Long>() {
@Override
public void onCompleted() {
System.exit(0);
} @Override
public void onError(Throwable e) { } @Override
public void onNext(Long aLong) {
System.out.println(aLong);
}
}); try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}

程序输出:

0
1

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

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

程序输出:

1
2
3
4
5

Skip

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

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

Observable.from(communities)
.skip(5)
.subscribe(new Action1<Community>() {
@Override
public void call(Community community) {
System.out.println(community.name);
}
});

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()的过滤规则是只允许还没有发射过的数据通过,所有重复的数据项都只会发射一次。

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

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

程序输出:

2 1 3 4 5

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

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

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

程序输出:

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

DistinctUntilChanged

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

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

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

程序输出:

2 1 2 3 4 3 4 5

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

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

Observable.from(houses)
.distinctUntilChanged(new Func1<House, String>() { @Override
public String call(House house) {
return house.communityName;
}
}).subscribe(new Action1<House>() {
@Override
public void call(House house) {
System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
}
});

程序输出:

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

First

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

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

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

程序输出:

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

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

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

Observable.from(houses)
.first(new Func1<House, Boolean>() {
@Override
public Boolean call(House house) {
return "竹园新村".equals(house.communityName);
}
})
.subscribe(new Action1<House>() {
@Override
public void call(House house) {
System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
}
});

程序输出:

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

Last

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

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

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

程序输出:

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

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

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

Observable.from(houses)
.last(new Func1<House, Boolean>() {
@Override
public Boolean call(House house) {
return "竹园新村".equals(house.communityName);
}
})
.subscribe(new Action1<House>() {
@Override
public void call(House house) {
System.out.println("小区:" + house.communityName + "; 房源描述:" + house.desc);
}
});

程序输出:

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

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

如果你喜欢我的文章,就关注下我的知乎专栏或者在 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. postgresql和oracle数据库对比

    SQL执行计划干预 从使用postgresql来看,想要改变执行计划只能通过対表进行分析,不能通过添加hint的方式来改变执行计划: oracle不仅可以通过对表进行收集统计来改变执行计划,而且很重要 ...

  2. freemarker的classic_compatible设置,解决报空错误

    前段时间接触freemaker时,本来后端写各接口运行正常,但加入了模板后,频繁报空指针问题,整了许久,最后还是请教了别人解决了这个问题,现在记录下来,方便以后碰到了可以查阅. 错误样例如下: ERR ...

  3. Git 初体验

    第一次接触git的时候,一直在纳闷git和github的区别,解释下,git是版本管理工具,github是开源共享平台,个人这么理解,理解这么多就行了 先说git吧,下载git客户端,地址:http: ...

  4. VS,连接到oracle 报要升级到8.多少版本的错

    1:确定服务器的oracle版本 2:本地的客户端版本要和服务器一致 3:操作系统位数要一致

  5. Ionic1开发环境配置ji

    配置Ionic1开发环境环境:windows7 32位+jdk1.8+ionic1.3,64位系统可以参考下面方法,软件注意选择对应的版本即可.    1.下载JDK并配置Java运行环境       ...

  6. 利用sfc文件构建网络渗透

      收集哈希 SCF(Shell命令文件)文件可用于执行一组有限的操作,例如显示Windows桌面或打开Windows资源管理器,这并不是什么新鲜事.然而,一个SCF文件可以用来访问一个特定的UNC路 ...

  7. JSON Web Token - 在Web应用间安全地传递信息

    转载自:http://blog.leapoahead.com/2015/09/06/understanding-jwt/ JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使 ...

  8. Android学习笔记2——shape

    Android有很多特别的xml文件,如常用的selector.style以及shape,熟练使用这些xml可以是我们的项目变得更个性化. 一.子标签(corners.gradient.padding ...

  9. 巨人大哥谈Web应用中的Session(session详解)

    巨人大哥谈Web应用中的Session(session详解) 虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术. ...

  10. beta冲刺6

    前言:此篇是补昨天凌晨的.后面有更新但是太晚了就没有即使更新.所以现在过来更新一下. 昨天的未完成: 用户测试+测试报告 目前剩下的功能点:输入内容检测 我的社团输出显示格式调整. 今天的完成: 我的 ...