RxJava操作符之Transforming Observables
在RxJava操作符之Creating Observables 我們學會了怎麼建立Observable,但是我們專案中往往會遇到很多複雜的情況,需要我們對資料進行過濾和轉化,以得到我們想要的結果。這篇文章我們主要是學習怎麼轉化資料:
Buffer
FlatMap
GroupBy
Map
Scan
Window
以上幾個操作符就是專門用來處理資料轉化功能的,接下來一個一個的來介紹吧。為了使程式碼看起來優雅一些,本篇開始都將使用lamda表示式。
Buffer
Buffer操作符就是將資料依據設定的大小做一下快取,然後將快取的資料作為一個集合發射出去。如下圖所示,第一張示例圖中我們指定buffer的大小為3,收集到3個資料後就發射出去,第二張圖中我們加入了一個skip引數用來指定每次發射一個集合需要跳過幾個資料,圖中如何指定count為2,skip為3,就會每3個資料發射一個包含兩個資料的集合,如果count==skip的話,我們就會發現其等效於第一種情況了。
在程式碼中使用也是一目瞭然的,對第一種情況
private Observable<Integer> getObservable() {
return Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
}
btn_buffer.setOnClickListener(v -> createObservable()
.buffer(3)
.subscribe(o -> Log.e("buffer", o + "")));
會得到以下結果:
buffer: [1, 2,3]
buffer: [4, 5,6]
buffer: [7, 8,9]
buffer: [10]
第二種情況只需要在buffer操作符多設定一個skip就好了:
private Observable<Integer> getObservable() {
return Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
}
btn_buffer.setOnClickListener(v -> createObservable()
.buffer(2, 3)
.subscribe(o -> Log.e("buffer", o + "")));
會得到以下結果:
buffer: [1, 2]
buffer: [4, 5]
buffer: [7, 8]
buffer: [10]
Buffer操作符就是將資料依據設定的大小做一下快取,然後將快取的資料作為一個集合發射出去,Buffer不僅設定數量規則,還可以設定時間:
private Observable bufferTimeObserver() {
return Observable.interval(1, TimeUnit.SECONDS).buffer(3, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread());
}
在上次我們講過Interval根據設定的時間發射一個資料,本例中是每秒發射一個資料,而buffer(3, TimeUnit.SECONDS),是設定每3秒將快取的資料發射出去。
Map
Map操作符會將資料直接 進行轉換,其和稍後要講的flatmap功能類似,但又有不同。先看map的原理圖:
從圖中可以看出,通過map操作符,設定資料轉換規則,將資料直接進行轉換。或許下圖能更清楚的數目map的作用:
其用法也是非常簡單的,下面我們就來驗證一下是否能得到想要的效果:
private Observable<Integer> getObservable() {
return Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
}
btn_map.setOnClickListener(v -> getObservable()
.map(integer -> integer *10)
.subscribe(integer1 -> Log.e("map", integer1 + "")));
map: 10
map: 20
map: 30
map: 40
map: 50
map: 60
map: 70
map: 80
map: 90
map: 100
將所有發出的資料都乘以了10,顯然得到了我們想要的資料。下面接著介紹更加強大的flatmap
Flatmap
FlatMap在專案中使用頻率很高的操作符,可以將要原資料(我們看做A型別的Observable)根據你想要的規則進行轉化成B型別Observable後再發射出去。其原理就是將這個Observable轉化為多個以原Observable發射的資料作為源資料的Observable,然後再將這多個Observable發射的資料整合發射出來,需要注意的是最後的順序可能會交錯地發射出來,如果需要順序輸出資料可以使用concatmap操作符。FlatMapIterable和FlatMap基相同,不同之處為其轉化的多個Observable是使用Iterable作為源資料的。
現在我們將原資料都加上flatmap字串怎麼實現呢?
btn_flatmap.setOnClickListener(v -> getObservable()
.flatMap(integer -> Observable.just("flatMap" + integer))
.subscribe(s -> {
Log.e("flatmap", s);
}));
private Observable<Integer> getObservable() {
return Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
}
注意和map操作符的區別,flatmap是需要將原始Observable轉換成目標Observable的,而map直接轉化資料
以下是程式執行的結果:
flatmap: flatMap1
flatmap: flatMap2
flatmap: flatMap3
flatmap: flatMap4
flatmap: flatMap5
flatmap: flatMap6
flatmap: flatMap7
flatmap: flatMap8
flatmap: flatMap9
flatmap: flatMap10
flatmap是需要好好掌握的,是一個功能強大的操作符。
GroupBy
GroupBy操作符將原始Observable發射的資料按照設定的key來拆分成一些小的Observable,然後這些小的Observable分別發射其所包含的的資料,類似資料庫查詢時groupBy。在使用中,我們需要提供一個生成key的規則,所有key相同的資料會分到同一個小的Observable中。
我們使用GroupBy把資料分成奇數和偶數,並且輸出偶數:
btn_groupby.setOnClickListener(v -> getObservable()
.groupBy(integer -> integer % 2 == 0)
.subscribe(booleanIntegerGroupedObservable -> {
if (booleanIntegerGroupedObservable.getKey()) {
booleanIntegerGroupedObservable.subscribe(integer -> Log.e("groupby"
, integer + ""));
}
}));
private Observable<Integer> getObservable() {
return Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
}
執行結果如下,很明顯得到了想要的結果:
groupby: 2
groupby: 4
groupby: 6
groupby: 8
groupby: 10
Scan
Scan操作符對一個序列的資料如{1,2,3,4}應用一個函式a*b,並將這個函式的結果1+2=3發射出去作為下個資料3應用這個函式時候的第一個引數使用,也就是3+3=6,有點類似於遞迴操作。通過scan我們可以很容易的實現斐波拉契數列。
btn_scan.setOnClickListener(v -> getObservable()
.scan((integer, integer2) -> integer +integer2)
.subscribe(integer1 -> Log.e("scan", "" + integer1)));
private Observable<Integer> getObservable() {
return Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
}
執行結果如下,
scan: 1
scan: 3
scan: 6
scan: 10
scan: 15
scan: 21
scan: 28
scan: 36
scan: 45
scan: 55
Window
Window操作符功能和我們前面講過的buffer類似,不同之處在於Window發射的是一些小的Observable物件,由這些小的Observable物件來發射內部包含的資料。同buffer一樣,window不僅可以通過數目來分組還可以通過時間等規則來分組
我們將{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}分成兩個Observable每個包含5個資料,看看window能否做到
btn_window.setOnClickListener(v -> getObservable()
.window(5)
.subscribe(integerObservable->{
integerObservable
.subscribe(integer -> Log.e("window"+integerObservable,integer+""));
}));
private Observable<Integer> getObservable() {
return Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
}
得到以下結果
windowrx.subjects.UnicastSubject@875d781: 1
windowrx.subjects.UnicastSubject@875d781: 2
windowrx.subjects.UnicastSubject@875d781: 3
windowrx.subjects.UnicastSubject@875d781: 4
windowrx.subjects.UnicastSubject@875d781: 5
windowrx.subjects.UnicastSubject@9c4026: 6
windowrx.subjects.UnicastSubject@9c4026: 7
windowrx.subjects.UnicastSubject@9c4026: 8
windowrx.subjects.UnicastSubject@9c4026: 9
windowrx.subjects.UnicastSubject@9c4026: 10
可以清晰看到確實有兩個Observable,rx.subjects.UnicastSubject@875d781和rx.subjects.UnicastSubject@9c4026,每個Observable包含5個資料。也是驗證上邊的結論。
總結:Transforming操作符,在Rxjava中經常使用,並且功能強大,所以一定要熟練的掌握轉換操作符。這樣才能靈活使用Rxjava。
相關文章
- RxJava操作符之組合操作符(六)RxJava
- 解剖 RxJava 之變換操作符RxJava
- 3章 RxJava操作符RxJava
- part05_Rxjava操作符RxJava
- RxJava2 操作符總結RxJava
- Kotlin 使用Rxjava的compose()操作符KotlinRxJava
- RxJava2.0——變換操作符RxJava
- RxJava 學習筆記 -- 條件操作符和布林操作符RxJava筆記
- RxJava2操作符學習筆記RxJava筆記
- RxJava 學習筆記 -- 變換操作符RxJava筆記
- RxJava 學習筆記 -- 過濾操作符RxJava筆記
- Spark Extracting,transforming,selecting featuresSparkORM
- RxJava2原始碼分析(二):操作符原理分析RxJava原始碼
- RxJava 原始碼分析系列(四) -操作符變換原理RxJava原始碼
- RxJava2.X 學習筆記 -- 建立操作符RxJava筆記
- RxJava常用操作符官方文件翻譯及Kotlin示例(1)RxJavaKotlin
- [譯] ECMAScript 的 Observables 提案
- Rxjava 2.x 原始碼系列 - 變換操作符 Map(上)RxJava原始碼
- RxJava從入門到不離不棄(四)——過濾操作符RxJava
- Rxjava深入理解之自己動手編寫RxjavaRxJava
- JavaScript騷操作之操作符JavaScript
- RxJs SwitchMapTo 操作符之移花接木JSAPT
- 四. RxJava之基本原理RxJava
- 課時6:Python之常用操作符Python
- Android開發之從零開始學RxJava 2.x(一)認識RxjavaAndroidRxJava
- Android RxJava: 這是一份全面的 操作符 使用匯總 (含詳細例項講解)AndroidRxJava
- RxJava練武場之——Token前置請求RxJava
- RxJava2系列之背壓策略(一)RxJava
- python操作符及資料型別之整形Python資料型別
- dart系列之:dart語言中的特殊操作符Dart
- RxJava2原始碼解讀之 Map、FlatMapRxJava原始碼
- RxJava小考題 -- Rxjava原始碼分析(一)RxJava原始碼
- 【填坑往事】使用Rxjava2的distinct操作符處理自定義資料型別去重的問題RxJava資料型別
- Android技能樹 - Rxjava原始碼(1) 之 初步結構AndroidRxJava原始碼
- RxJava梳理RxJava
- Retrofit + RxJavaRxJava
- dart基礎之類介面操作符過載相關Dart
- Kotlin——高階篇(五):集合之常用操作符彙總Kotlin
- 一元操作符“++”,“- ” 之強制轉換數值