RxJava——基礎學習(六),過濾操作符

學習資料

1.過濾操作符

作用:對Observable發射的 數據序列 進行 過濾或選擇

1.1 first

只發射第一個或者第一個滿足某個條件的數據項

1.1.1 first()第一項

簡單使用:

public class FirstDemo {
    public static void main(String[] args) {
        first();
    }

    /**
     * 只發送第一項數據
     */
    private static void first() {
        Observable
                .just(1,2,3,4)
                .first()
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        System.out.println(integer);
                    }
                });
    }
}

運行結果:

1

1.1.2 first(Func1)

只發送第一個滿足條件的數據

簡單使用:

    /**
     * 第一個偶數
     */
    private static void firstTrue() {
        Observable
                .just(1,3,4,5)
                .first(new Func1<Integer, Boolean>() {
                    @Override
                    public Boolean call(Integer integer) {
                        return integer % 2 == 0;
                    }
                })
                .subscribe((i)->System.out.println("第一個偶數:" + i));
    }

運行結果:

第一個偶數:4

last正好與first相反,是只發送最后一個或者最后一個滿足條件的數據項


1.2 take

只發送前N項數據

1.2.1 take(int)

只發送前int項數據項,默認不任何特定的調度器上執行

簡單使用:

    /**
     * 只發送前5項數據
     */
    private static void takeInt() {
        Observable
                .interval(500, TimeUnit.MILLISECONDS, Schedulers.immediate())
                .take(5)
                .subscribe((i) -> System.out.print(i + " ,"));
    }

運行結果:

0 ,1 ,2 ,3 ,4 ,

1.2.2 take(long,TimeUnit,Scheduler)

在寫定的時間段內,會發送Observable發出的數據項,默認在computation運算調度器上執行

簡單使用:

    /**
     * 發送1s以內的數據項
     */
    private static void takeTime() {
        Observable
                .interval(100, TimeUnit.MILLISECONDS, Schedulers.immediate())
                .take(1,TimeUnit.SECONDS ,Schedulers.newThread())
                .subscribe((i) -> System.out.print(i + " ,"));
    }

運行結果:

0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,

發送的數據項只是1s以內的,并不包括1s時的

takeLast是只發送后n項數據


1.3 Skip

跳過數據項

1.3.1 skip(int)

跳過Observable發送的前n項數據項,默認不在任何特定的調度器上執行

簡單使用:

    /**
     * 跳過前3項數據
     */
    private static void skipInt() {
        Observable
                .range(1,10)
                .skip(3)
                .subscribe((i) -> System.out.print(i + " ,"));
    } 

運行結果:

4 ,5 ,6 ,7 ,8 ,9 ,10 ,

1.3.2 skip(long,TimeUnit,Scheduler)

跳過給定的時間段內Obsvable發送過來的數據項,默認在computation運算調度器上執行

簡單使用:

    /**
     * 發送前5個,500毫秒之后的數據項
     */
    private static void skipTime() {
        Observable
                .interval(100, TimeUnit.MILLISECONDS, Schedulers.immediate())
                .skip(500,TimeUnit.MILLISECONDS)
                .take(5)
                .subscribe((i) -> System.out.print(i + " ,"));
    }

運行結果:

4 ,5 ,6 ,7 ,8 ,

SkipLast就是跳過后n個數據項


1.4 Sample

定期發射Observable最近發射的數據項

1.4.1 sample(long,TimeUnit)

定時查看一個Observable,然后將自上次采樣后,Observable最近一次發送的數據發送出去,默認在默認在computation調度器上執行

注意:如果從上次采樣后,原始的Observable沒有發出數據項,sample操作返回的新的Observable在監測期時間內也不會發射任何數據

簡單使用:

    /**
     * 每隔100毫秒,將Observable最近一個發送的數據項發送出去
     */
    private static void sampleTime() {
        Observable
                .interval(30,TimeUnit.MILLISECONDS, Schedulers.immediate())
                .sample(100, TimeUnit.MILLISECONDS)
                .take(5)
                .subscribe((i) -> System.out.print(i + " ,"));

    }

運行結果:

1 ,5 ,8 ,11 ,15 ,

1.4.2 sample(Observable)

  • sample(signal)

當監測到名字為signalObaervable發過來一個信號或者終止時,就對原始Observable發送的數據進行采樣,然后將自從上次采樣以來最近一次發送的數據發送出去

默認不在任何特定的調度器上執行

簡單使用:

    /**
     * 每當收到信號時,將最近發送的一個數據項發送出去
     */
    private static void sameSignal() {
        Observable
                .interval(30,TimeUnit.MILLISECONDS, Schedulers.immediate())
                .sample(Observable.interval(100,TimeUnit.MILLISECONDS))
                .take(5)
                .subscribe((i) -> System.out.print(i + " ,"));
    }

運行結果:

2 ,5 ,8 ,12 ,15 ,

第一個輸出的數字是2,因為是從0開始的,每次輸出的數字中間都會間隔2個


1.5 Debounce

兩次發送數據項間隔大于一段指定的時間,才發射一個數據

注意:最后的onCompleted信號,會緊隨著最后一項原始Observable數據項,即使是小于時間間隔,一旦結束到onCompleted信號,整個操作也就結束了,onCompleted通知不會觸發限流

1.5.1 debounce(long,TimeUnit)

在指定的時間long間隔進行限流,個人理解,過濾兩次數據小于指定間隔的數據項,與上次發送的時間差大于間隔的數據項才進行發送

默認在computation調度器上執行

簡單使用:

    /**
     * 輸出兩次間隔大于150秒的數據項
     */
    private static void deBounceTime() {
        Observable
                .create(new Observable.OnSubscribe<Integer>() {
                    @Override
                    public void call(Subscriber<? super Integer> subscriber) {
                        try {
                            for (int i = 0; i < 5; i++) {
                                //產生在100到200間隨機時間間隔
                                TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 100 + 100));
                                subscriber.onNext(i);
                            }
                             //延遲結束信號 否則最后一次一定不會發送
                            TimeUnit.MILLISECONDS.sleep(100);
                            subscriber.onCompleted();
                        } catch (InterruptedException e) {
                            subscriber.onError(e);
                        }
                    }
                })
                .debounce(150, TimeUnit.MILLISECONDS, Schedulers.newThread())
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
                        System.out.println(" --> onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                         System.out.println(e.getMessage());
                    }

                    @Override
                    public void onNext(Integer integer) {
                        System.out.print(integer + " ,");
                    }
                });
    }

運行結果:

2 ,4 , --> onCompleted

注意subscriber.onCompleted()發送結束通知信號的時機


1.5.2 debounce(Func1)

對原始Observable的每一個數據項應用一個函數進行限流,這個函數返回一個Observable。接到通知前,原始Observable發送的數據項將會被抑制

默認不在任何特定的調度器上執行

簡單使用:

    /**
     * 在沒有接到通知的150毫秒內,原始Observable發送的數據項將會被抑制
     */
    private static void deBounceSignal() {
        Observable
                .create((subscriber) -> {
                    try {
                        for (int i = 0; i < 5; i++) {
                            //產生在100到200間隨機時間間隔
                            TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 100 + 100));
                            subscriber.onNext(i);
                        }
                        //延遲結束信號 否則最后一次一定不會發送
                        TimeUnit.MILLISECONDS.sleep(100);
                        subscriber.onCompleted();
                    } catch (InterruptedException e) {
                        subscriber.onError(e);
                    }
                })
                .debounce(new Func1<Object, Observable<Long>>() {
                    @Override
                    public Observable<Long> call(Object o) {
                        //每隔150毫秒發出一個通知
                        return Observable.interval(150, TimeUnit.MILLISECONDS);
                    }
                })
                .subscribe(new Subscriber<Object>() {
                    @Override
                    public void onCompleted() {
                        System.out.println(" --> onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println(e.getMessage());
                    }

                    @Override
                    public void onNext(Object o) {
                        System.out.print(o + " ,");
                    }
                });
    }   

運行結果:

0 ,2 ,4 , --> onCompleted

注意:最后一個數據項一定會被發送,即使在沒有接到通知的150毫秒內


1.6 Distinct

過濾掉重復的數據項,默認不在任何特定的調度器上執行

1.6.1 distinct()

簡單使用:

    /**
     * 去除重復項
     */
    private static void distinct() {
        Observable
                .just(1,2,2,3,4,4,5,6,6)
                .distinct()
                .subscribe((i) -> System.out.print(i+" ,"));
    }

運行結果:

1 ,2 ,3 ,4 ,5 ,6 ,

1.6.2 distinct(Func1)

將原始Observable發送的數據項應用一個函數,根據這個函數產生不同的key,之后的數據項便是比較key,而不再管數據項

簡單使用:

    /**
     * 根據條件指定過濾的key ,將之后出現 key為"1","2",全部過濾
     */
    private static void distinctKey() {
        Observable
                .just(1,2,2,3,3,4,5,6,6)
                .distinct(new Func1<Integer, String>() {
                    @Override
                    public String call(Integer integer) {
                        //設置key
                        return integer / 2 == 0 ? "1" : "2" ;
                    }
                })
                .subscribe((i) -> System.out.print(i+" ,"));
    }

運行結果:

1 ,2 ,

1.7 ElementAt

只發射索引值為N的數據項,索引從0開始

如果傳遞的索引為負數,或者索引不小于數據項個數,將會拋出一個IndexOutOfBoundsException異常

簡單使用:

public class ElementAtDemo {
    /**
     * 輸出索引值為5的數據項,從0開始
     */
    public static void main(String[] args) {
        Observable
                .range(1,10)
                .elementAt(5)
                .subscribe(System.out::println);
    }
}

運行結果:

6

1.8 IgnoreElements

不發射任何數據,只發射Observable的終止通知onErroronCompleted

ignoreElements

若不關心Obsvable發送的數據項,只想在完成時,或者遇到錯誤終止時收到通知,可以使用,這個操作符永遠不會調用觀察者的onNext()方法

默認不在任何特定的調度器上執行


2. 最后

感覺過濾操作符比變換操作符理解起來要容易一些

本人很菜,有錯誤請指出

共鳴 :)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容

  • 本篇文章介主要紹RxJava中操作符是以函數作為基本單位,與響應式編程作為結合使用的,對什么是操作、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,881評論 0 10
  • 作者: maplejaw本篇只解析標準包中的操作符。對于擴展包,由于使用率較低,如有需求,請讀者自行查閱文檔。 創...
    maplejaw_閱讀 45,723評論 8 93
  • 創建操作 用于創建Observable的操作符Create通過調用觀察者的方法從頭創建一個ObservableEm...
    rkua閱讀 1,850評論 0 1
  • 注:只包含標準包中的操作符,用于個人學習及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 2,209評論 2 8
  • 劉啟敏閱讀 1,883評論 1 7