RxJava系列四(過濾操做符)

轉載請註明出處:https://zhuanlan.zhihu.com/p/21966621java


前面一篇文章中咱們介紹了轉換類操做符,那麼這一章咱們就來介紹下過濾類的操做符。顧名思義,這類operators主要用於對事件數據的篩選過濾,只返回知足咱們條件的數據。過濾類操做符主要包含: Filter Take TakeLast TakeUntil Skip SkipLast ElementAt Debounce Distinct DistinctUntilChanged First Last等等。ip

Filter

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

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個元素。

clipboard.png

獲取小區列表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並終止。

clipboard.png

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方法來判斷是否須要終止發射數據。

clipboard.png

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項數據。

clipboard.png

過濾掉小區列表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項數據。

clipboard.png

ElementAt

elementAt(int)用來獲取元素Observable發射的事件序列中的第n項數據,並當作惟一的數據發射出去。

clipboard.png

Debounce

debounce(long, TimeUnit)過濾掉了由Observable發射的速率過快的數據;若是在一個指定的時間間隔過去了仍舊沒有發射一個,那麼它將發射最後的那個。一般咱們用來結合RxBing(Jake Wharton大神使用RxJava封裝的Android UI組件)使用,防止button重複點擊。

clipboard.png

debounce(Func1)能夠根據Func1的call方法中的函數來過濾,Func1中的中的call方法返回了一個臨時的Observable,若是原始的Observable在發射一個新的數據時,上一個數據根據Func1的call方法生成的臨時Observable還沒結束,那麼上一個數據就會被過濾掉。

clipboard.png

Distinct

distinct()的過濾規則是隻容許尚未發射過的數據經過,全部重複的數據項都只會發射一次。

clipboard.png

過濾掉一段數字中的重複項:

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()同樣過濾掉重複的數據項。

clipboard.png

假設咱們要過濾掉一堆房源中小區名重複的小區:

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發射的當前數據項和前一個數據項是否相同。

clipboard.png

一樣仍是上面過濾數字的例子:

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來判斷兩個相鄰的數據項是否相同。

clipboard.png

咱們仍是拿前面的過濾房源的例子:

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只發送觀測序列中的第一個數據項。

clipboard.png

獲取房源列表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)只發送符合條件的第一個數據項。

clipboard.png

如今咱們要獲取房源列表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()只發射觀測序列中的最後一個數據項。

clipboard.png

獲取房源列表中的最後一套房源:

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

程序輸出:

小區:中糧·海景壹號; 房源描述:南北通透,豪華五房

last(Func1)只發射觀測序列中符合條件的最後一個數據項。

clipboard.png

獲取房源列表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。

相關文章
相關標籤/搜索