RxJava2.0 操作符(3)—— Filter 過濾轉換符

weixin_34402408發表於2017-10-16

這個頁面展示的操作符可用於過濾和選擇Observable發射的資料序列。
Debounce — 僅在過了一段指定的時間還沒發射資料時才發射一個資料。
Distinct — 過濾掉重複資料。
ElementAt — 發射第 N 項資料。
Filter — 過濾資料。
First 只發射第一項資料。
IgnoreElements — 丟棄所有的正常資料,只發射錯誤或完成通知。
Last — 只發射最後的一項資料。
Sample 定期發射 Observable 最近的資料。
Skip — 跳過開始的 N 項資料。
SkipLast — 跳過最後的 N 項資料。
Take — 只發射開始的 N 項資料。
TakeLast — 只發射最後的 N 項資料。

3.1 Debounce

僅在過了一段指定的時間還沒發射資料時才發射一個資料,過濾掉髮射速率過快的資料項。
通俗一點來說,N 個事件的結點發生的時間太接近,debounce 過濾掉前 N-1 個事件。
實踐:常用於過濾實時的搜尋、防止按鈕重複點選。


debounce

示例程式碼:

Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Exception {
            for (int i = 0; i < 7; i++) {
                emitter.onNext(i);
                Thread.sleep(i * 100);
            }
            emitter.onComplete();

        }
    }).debounce(300, TimeUnit.MILLISECONDS).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.e(TAG, integer + "");
        }
    });

輸出結果:

4
5
6

next 傳送時與上一個 next 間隔少於 300 毫秒所以不傳送0,1,2,3。
操作符 throttleWithTimeout 和 debounce 效果一致。

3.1 Distinct

過濾掉重複資料,只允許還沒有發射過的資料項通過。


distinct

示例程式碼1:

Observable.just(1, 2, 1, 1, 2, 3)
    .distinct()
    .subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.e(TAG, integer + "");
        }
    });

輸出結果:

1 2 3

3.1.1 Distinct(Function)

distinct

這個操作符有一個變體接受一個函式。這個函式根據原始 Observable 發射的資料項產生一個 Key,然後,比較這些 Key 而不是資料本身,來判定兩個資料是否是不同的。
示例程式碼:

Observable.just(-1, -2, 0, 1, 2, 1).distinct(new Function<Integer, Integer>() {
        @Override
        public Integer apply(@NonNull Integer integer) throws Exception {
            return Math.abs(integer);
        }
    }).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.e(TAG, integer + "");
        }
    });

輸出結果:

-1 , -2 , 0

3.1.2 DistinctUntilChanged

過濾掉連續重複的資料,判定一個資料和它的直接前驅(相鄰)是否是不同的。


distinctUntilChanged

示例程式碼:

  Observable.just(-1, 1, 1, 2, 1, 2, 2)
      .distinctUntilChanged()
      .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(@NonNull Integer integer) throws Exception {
                Log.e(TAG, integer + "");
            }
        });

輸出結果:

-1,1,2,1,2

3.1.3 DistinctUntilChanged(Function)

過濾掉連續重複的資料,通過一個 key 判定一個資料和它的直接前驅(相鄰)是否是不同的。


distinctUntilChanged(Function)

示例程式碼:

Observable.just(-1, -2, -1, 1, 2, 1).distinctUntilChanged(new Function<Integer, Integer>() {
        @Override
        public Integer apply(@NonNull Integer integer) throws Exception {
            return Math.abs(integer);
        }
    }).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.e(TAG, integer + "");
        }
    });

輸出結果:

-1 , -2 , -1 , 2 , 1

3.3 ElementAt

發射第 N 項資料,操作符獲取原始 Observable 發射的資料序列指定索引位置的資料項,然後當做自己的唯一資料發射。


elementAt1

示例程式碼:

Observable.just(2,3,4,5).elementAt(2).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(@NonNull Integer integer) throws Exception {
        Log.e(TAG, integer + "");
    }
});

輸出結果:

4

ElementAt(long index, T defaultItem)
發射第 N 項資料,如果 Observable 資料少於N項就發射預設值,原始 Observable 的資料項數小於 index,使用預設的 defaultItem 資料。


elementAt2

示例程式碼:

Observable.just("h", "e", "l", "l", "0")
    .elementAt(6, "dafalut")
    .subscribe(new Consumer<String>() {
            @Override
            public void accept(@NonNull String s) throws Exception {
                Log.e(TAG, "");
            }
        });

輸出結果:

dafalut

3.4 Filter

Filter 操作符使用你指定的一個函式過濾資料項,只有滿足條件的資料才會被髮射。


Filter

示例程式碼:

 Observable.just(1,2,3,4,5,6,7)
    .filter(new Predicate<Integer>() {
        @Override
        public boolean test(@NonNull Integer integer) throws Exception {
            return integer > 2 && integer < 6;
        }
    }).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.e(TAG, integer+"");
        }
    });

輸出結果:

3,4,5

3.5 First

返回一個 Single,它僅發出 Observable 發出的第一個專案,或者如果 Observable 不傳送任何專案,則返回一個預設專案。first = elementAt(0L, defaultItem);


First

示例程式碼1:

Observable.just(1,2).first(100).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(@NonNull Integer integer) throws Exception {
        Log.e(TAG, integer+"");
    }
});

輸出結果:

1

示例程式碼2:

//建立一個不發射任何資料但是正常終止的 Observable ,則返回預設的字元“ empty default ”
Observable.empty().first("empty default").subscribe(new Consumer<Object>() {
        @Override
        public void accept(@NonNull Object o) throws Exception {
            Log.e(TAG, o.toString());
        }
    });

輸出結果:

empty default

3.6 IgnoreElements

不發射任何資料,只發射 Observable 的終止通知


IgnoreElements

示例程式碼:

Observable.just(1, 2, 3).ignoreElements().subscribe(new Action() {
        @Override
        public void run() throws Exception {
            Log.e(TAG, "什麼意思呢");
        }
    });

輸出結果:

什麼意思呢

3.7 Last

只發出一個 Observable 發出的最後一個專案(或者滿足某些條件的最後一個專案)(PS:與 First 對應)


last

如果您只對 Observable 發出的最後一個專案或滿足某些條件的最後一個專案感興趣,則可以使用 Last 操作符過濾 Observable。
在某些實現中,Last 不是作為返回 Observable 的過濾運算子實現的,而是作為阻止函式,當 Observable 終止時返回特定項。 在這些實現中,如果您想要一個過濾操作符,那麼建議你使用操作符 TakeLast(1)
示例程式碼 1:

// 發射倒數第一個元素
Observable.just(-1, -2, 0, 1, 2).last(3).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(@NonNull Integer integer) throws Exception {
        Log.e(TAG, integer + "");
    }
});

輸出結果:

2

3.8 Sample

定期發射 Observable 發射的最後一條資料。

sample

Sample 操作符定時檢視一個 Observable,然後發射自上次取樣以來它最近發射的資料。

在某些實現中,有一個 ThrottleFirst 操作符的功能類似,但不是發射取樣期間的最近的資料,而是發射在那段時間內的第一項資料。
RxJava 將這個操作符實現為 Sample 和 ThrottleLast。
注意:如果自上次取樣以來,原始 Observable 沒有發射任何資料,這個操作返回的 Observable 在那段時間內也不會發射任何資料。

3.8.1 Sample

示例程式碼:

//取300毫秒內,傳送的最後一次事件
Observable.interval(100, TimeUnit.MILLISECONDS)
    .sample(330, TimeUnit.MILLISECONDS)
    .take(3)
    .subscribe(new Consumer<Long>() {
        @Override
        public void accept(@NonNull Long aLong) throws Exception {
            Log.e(TAG, "accept:" + aLong);
        }
    });

輸出結果:

accept:2
accept:5
accept:8

3.8.2 throttleLast

總是發射原始 Observable 的第一項資料,而不是最近的一項。
實踐:常於防止按鈕重複點選。


throttleLast

示例程式碼:

//取300毫秒內,傳送的最後一次事件
Observable.interval(100, TimeUnit.MILLISECONDS)
    .throttleLast(330, TimeUnit.MILLISECONDS)
    .take(3)
    .subscribe(new Consumer<Long>() {
        @Override
        public void accept(@NonNull Long aLong) throws Exception {
            Log.e(TAG, "accept:" + aLong);
        }
    });

輸出結果:

accept:1
accept:5
accept:7

3.8.3 throttleFirst

總是發射原始 Observable 的第一項資料,而不是最近的一項。
實踐:常於防止按鈕重複點選。


throttleFirst

示例程式碼:

//取300毫秒裡第一次發出的事件
Observable.interval(100, TimeUnit.MILLISECONDS)
    .throttleFirst(330, TimeUnit.MILLISECONDS)
    .take(3)
    .subscribe(new Consumer<Long>() {
        @Override
        public void accept(@NonNull Long aLong) throws Exception {
            Log.e(TAG, "accept" + aLong);
        }
    });

輸出結果:

accept:0
accept:4
accept:8

3.9 Skip

抑制 Observable 發射的前 N 項資料,只保留之後的資料。

skip

示例程式碼:

Observable.just(1, 2, 3, 4, 5).skip(3).subscribe(new Consumer<Integer>() {
        @Override
        public void accept(@NonNull Integer integer) throws Exception {
            Log.e(TAG, integer + "");
        }
    });

輸出結果:

4
5

3.10 SkipLast

與 skip 相反,抑制 Observable 發射的前 N 項資料,只保留前面的資料。


skipLast

示例程式碼:

Observable.just(13, 8, 5, 3, 2, 1).skipLast(4).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(@NonNull Integer integer) throws Exception {
        Log.e(TAG, integer + "");
    }
});

輸出結果:

13
8

3.11 Take

只發射開始的 N 項資料。


rxjava_take

示例程式碼:

//從1開始計時,輸出前五項
Observable.interval(1, TimeUnit.SECONDS)
        .take(5)
        .subscribe(new Consumer<Long>() {
            @Override
            public void accept(@NonNull Long aLong) throws Exception {
                Log.e(TAG, aLong + "");
            }
        });

輸出結果:

1,2,3,4,5

3.12 TakeLast

發射 Observable 發射的最後 N 項資料.

rxjava_takeLat

示例程式碼:

//只輸出最後三項
Observable.just(13, 8, 5, 3, 2, 1).takeLast(3).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(@NonNull Integer integer) throws Exception {
        Log.e(TAG, integer + "");
    }
});

輸出結果:

3,2,1

相關文章