轉載請註明出處:https://zhuanlan.zhihu.com/p/21966621java
RxJava系列2(基本概念及使用介紹)github
前面一篇文章中咱們介紹了轉換類操做符,那麼這一章咱們就來介紹下過濾類的操做符。顧名思義,這類operators主要用於對事件數據的篩選過濾,只返回知足咱們條件的數據。過濾類操做符主要包含: Filter
Take
TakeLast
TakeUntil
Skip
SkipLast
ElementAt
Debounce
Distinct
DistinctUntilChanged
First
Last
等等。ip
filter(Func1)
用來過濾觀測序列中咱們不想要的值,只返回知足條件的值,咱們看下原理圖:element
仍是拿前面文章中的小區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(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(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(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(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(int)
忽略Observable發射的後n項數據。
elementAt(int)
用來獲取元素Observable發射的事件序列中的第n項數據,並當作惟一的數據發射出去。
debounce(long, TimeUnit)
過濾掉了由Observable發射的速率過快的數據;若是在一個指定的時間間隔過去了仍舊沒有發射一個,那麼它將發射最後的那個。一般咱們用來結合RxBing(Jake Wharton大神使用RxJava封裝的Android UI組件)使用,防止button重複點擊。
debounce(Func1)
能夠根據Func1的call方法中的函數來過濾,Func1中的中的call方法返回了一個臨時的Observable,若是原始的Observable在發射一個新的數據時,上一個數據根據Func1的call方法生成的臨時Observable還沒結束,那麼上一個數據就會被過濾掉。
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()
和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來判斷兩個相鄰的數據項是否相同。
咱們仍是拿前面的過濾房源的例子:
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()
顧名思義,它是的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()
只發射觀測序列中的最後一個數據項。
獲取房源列表中的最後一套房源:
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。