RxJava 教程第二部分:事件流基礎之 檢查數據

hvnkm 8年前發布 | 6K 次閱讀 RxJava Java開發

Inspection 檢查數據是否符合某一條件

前面一節介紹了如何過濾掉我們不關心的數據。有時候我們需要了解該數據流中的數據是否符合某一條件。本節來介紹一些檢查數據流中數據的函數。

all

all 函數用來判斷 observable 中發射的所有數據是否都滿足一個條件。

public final Observable<java.lang.Boolean> all(Func1<? super T,java.lang.Boolean> predicate)
 
Observable<Integer> values = Observable.create(o -> {
    o.onNext(0);
    o.onNext(10);
    o.onNext(10);
    o.onNext(2);
    o.onCompleted();
});
 
 
SubscriptionevenNumbers = values
    .all(i -> i % 2 == 0)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

true
Completed
 

all 函數返回的是一個發射一個 布爾值的 Observable,而不是直接返回一個 布爾值。原因在于我們并不知道源 Observable 何時才結束數據流的發射,只有當源 Observable 發射結束的時候, all 函數才知道結果是否都滿足條件。只要遇到一個不滿足條件的數據,all 函數就立刻返回 false。 只有當源 Observable 結束發射并且所發射的所有數據都滿足條件的時候才會產生 true。在 observable 內返回結果可以方便的實現非阻塞操作。 在下個示例中可以看到 all 在遇到不滿足的數據的時候就立刻結束了。

Observable<Long> values = Observable.interval(150, TimeUnit.MILLISECONDS).take(5);
 
Subscriptionsubscription = values
    .all(i -> i<3) // Will fail eventually
    .subscribe(
        v -> System.out.println("All: " + v),
        e -> System.out.println("All: Error: " + e),
        () -> System.out.println("All: Completed")
    );
Subscriptionsubscription2 = values
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

0
1
2
All: false
All: Completed
3
4
Completed
 

如果源 Observable 出現了錯誤,則 all 操作就沒有意義了,all 會直接發射一個 error 然后結束。

Observable<Integer> values = Observable.create(o -> {
    o.onNext(0);
    o.onNext(2);
    o.onError(new Exception());
});
 
Subscriptionsubscription = values
    .all(i -> i % 2 == 0)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

Error: java.lang.Exception
 

如果源 Observable 在出錯之前就發射了一個不滿足條件的數據,則 源 Observable 的錯誤對 all 沒有影響( all 遇到不滿足條件的數據就結束了,結束的Observable 無法再繼續發射數據了)。

Observable<Integer> values = Observable.create(o -> {
    o.onNext(1);
    o.onNext(2);
    o.onError(new Exception());
});
 
Subscriptionsubscription = values
    .all(i -> i % 2 == 0)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

false
Completed
 

exists

如果源 exists 發射的數據中有一個滿足條件,則 exists 就返回 true。 exists 和 all 一樣也是返回一個 Observable 而不是直接返回 布爾值。

Observable<Integer> values = Observable.range(0, 2);
 
Subscriptionsubscription = values
    .exists(i -> i > 2)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

false
Completed
 

上面示例中只發射了 0 和1 兩個數據,而這兩個數據都不滿足大于2的條件,所以返回結果為 false。如果我們多發射幾個數據,則就會滿足條件了。

Observable<Integer> values = Observable.range(0, 4);
 

結果:

true
Completed
 

isEmpty

顧名思義,判斷一個 Observable 是否是空的,也就是沒有發射任何數據就結束了。

Observable<Long> values = Observable.timer(1000, TimeUnit.MILLISECONDS);
 
Subscriptionsubscription = values
    .isEmpty()
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

false
Completed
 

只要源 Observable 發射了一個數據,isEmpty 就立刻返回 false, 只有當源 Observable 完成了并且沒有發射數據,isEmpty 才返回 true。

contains

contains 使用 Object.equals 函數來判斷源 Observable 是否發射了相同的數據。只要遇到相同的數據,則 contains 就立刻返回。

Observable<Long> values = Observable.interval(100, TimeUnit.MILLISECONDS);
 
Subscriptionsubscription = values
    .contains(4L)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

true
Completed
 

注意上面使用的是 contains(4L), 而不是 contains(4), 由于 values 是 Observable

類型的, 所以需要使用 Long 類型而不能是 Integer 類型。

如果使用 contains(4) 則什么都不會打印出來, 由于 values 是一個無限的數據流,所以 contains 一直在等待一個相同的數據發射出來,但是在 values 里面是沒有一樣的數據的,導致 contains 一直等待下去。

 

defaultIfEmpty

如果你不想單獨處理沒有發射任何數據的情況(需要用 isEmpty 函數來檢查是否為空),則可以使用 defaultIfEmpty 函數來強制一個空的 Observable 發射一個默認數據。

Observable<Integer> values = Observable.empty();
 
Subscriptionsubscription = values
    .defaultIfEmpty(2)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

2
Completed
 

只有當 onCompleted 事件發生了,并且 Observable 沒有發射任何數據的時候,才會使用默認值;否則不會使用默認值。 如果發生了錯誤,則還會有錯誤的結果。

Observable<Integer> values = Observable.error(new Exception());
 
Subscriptionsubscription = values
    .defaultIfEmpty(2)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

Error: java.lang.Exception
 

elementAt

從特定的位置選擇一個數據發射。

Observable<Integer> values = Observable.range(100, 10);
 
Subscriptionsubscription = values
    .elementAt(2)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

102
Completed
 

該函數和訪問數組或者集合類似,如果 Observable 發射的數據個數沒有這么多,則會拋出 java.lang.IndexOutOfBoundsException 。可以使用一個默認值(elementAtOrDefault)來避免拋出 java.lang.IndexOutOfBoundsException。

Observable<Integer> values = Observable.range(100, 10);
 
Subscriptionsubscription = values
    .elementAtOrDefault(22, 0)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

0
Completed
 

sequenceEqual

本節最后這個操作函數是用來比較兩個 Observable 發射的數據是否是一樣的,同樣位置的數據是一樣的。要求兩個 Observable 發射的數據個數是一樣的并且每個位置上的數據也是一樣的。 該函數內部用 Object.equals 來比較數據,當然你也可以自己指定一個比較函數。

Observable<String> strings = Observable.just("1", "2", "3");
Observable<Integer> ints = Observable.just(1, 2, 3);
 
Observable.sequenceEqual(strings, ints, (s,i) -> s.equals(i.toString()))
//Observable.sequenceEqual(strings, ints)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

true
Completed
 

上面使用了自定義的比較函數,所以結果是一樣的。 如果不指定自定義的 比較函數的話, 使用默認的 Object.equals 來比較,則返回的結果就是 False 了。

如果一個源 Observable 出現了 錯誤,則 比較結果的 Observable 也會出現 錯誤并結束。

Observable<Integer> values = Observable.create(o -> {
    o.onNext(1);
    o.onNext(2);
    o.onError(new Exception());
});
 
Observable.sequenceEqual(values, values)
    .subscribe(
        v -> System.out.println(v),
        e -> System.out.println("Error: " + e),
        () -> System.out.println("Completed")
    );
 

結果:

Error: java.lang.Exception
 

 來自: http://blog.chengyunfeng.com/?p=961

 本文由用戶 hvnkm 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!