1. 程式人生 > >Rxjava(2.操作符)

Rxjava(2.操作符)

參考地址

本文主要分為:

寫下本文原因:
加深印象+理解+後期鞏固

1.準備工作

假如我有這樣一個方法:
這個方法根據傳入的字串返回一個網站的url列表結果:

Observable<List<String>> query(String text);  

現在需要請求這個方法拿到List列表結果並顯示:

query("Hello, world!")  
    .subscribe(urls -> {  
        for (String url : urls) {  
            System.out
.println(url); } });

這種程式碼使我們喪失了變化資料流的能力。一旦想要更改每一個URL,只能在Subscriber(觀察者)中來做。此時我們就可以用上一節所講的map()操作符!!!

但是,map的輸入是urls列表,處理的時候還是要for each遍歷,一樣很蛋疼。

萬幸的是,還有Observable.from()方法,它接收一個集合作為輸入,然後每次輸出集合中的一個元素給subscriber(觀察者):

Observable.from("url1", "url2", "url3")  
    .subscribe(url -> System.out
.println(url)); //輸出結果分別為: url1 url2 url3

最後。。。我們來把這個方法用到剛才的場景,就變為了:

query("Hello, world!")  
    .subscribe(urls -> {  
        Observable.from(urls)  
            .subscribe(url -> System.out.println(url));  
    });  

上面的程式碼雖然去掉了for each迴圈,但是程式碼依然看起來很亂。多個巢狀的subscription不僅看起來很醜,難以修改,更嚴重的是它會破壞某些我們現在還沒有講到的RxJava的特性。

2.改進:flatMap()操作符

Observable.flatMap()接收一個Observable的輸出作為輸入,同時輸出另外一個Observable。

直接看程式碼:

query("Hello, world!")  
    .flatMap(new Func1<List<String>, Observable<String>>() {  
        @Override  
        public Observable<String> call(List<String> urls) {  
            return Observable.from(urls);  
        }  
    })  
    .subscribe(url -> System.out.println(url));  
query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .subscribe(url -> System.out.println(url)); 

flatMap()是不是看起來很奇怪?為什麼它要返回另外一個Observable呢?
理解flatMap的關鍵點在於,flatMap輸出的新的Observable正是我們在Subscriber想要接收的。現在Subscriber不再收到List,而是收到一些列單個的字串,就像Observable.from()的輸出一樣。

這部分也是我當初學RxJava的時候最難理解的部分,一旦我突然領悟了,RxJava的很多疑問也就一併解決了。

3.還可以更好

flatMap()實在不能更讚了,它可以返回任何它想返回的Observable物件。
比如下面的方法:

// 返回網站的標題,如果404了就返回null  
Observable<String> getTitle(String URL);

接著前面的例子,現在我不想列印URL了,而是要列印收到的每個網站的標題。問題來了,我的方法每次只能傳入一個URL,並且返回值不是一個String,而是一個輸出String的Observabl物件。使用flatMap()可以簡單的解決這個問題。

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(new Func1<String, Observable<String>>() {  
        @Override  
        public Observable<String> call(String url) {  
            return getTitle(url);  
        }  
    })  
    .subscribe(title -> System.out.println(title));  

使用lambda:

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(url -> getTitle(url))  
    .subscribe(title -> System.out.println(title)); 

4.豐富的操作符

  • filter():輸出和輸入相同的元素,並且會過濾掉那些不滿足檢查條件的。
  • take():輸出最多指定數量的結果。
  • doOnNext():允許我們在每次輸出一個元素之前做一些額外的事情,比如下文的儲存標題。
  • filter操作符

getTitle()返回null如果url不存在。我們不想輸出”null”,那麼我們可以從返回的title列表中過濾掉null值!

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(url -> getTitle(url))  
    .filter(title -> title != null)  
    .subscribe(title -> System.out.println(title));  
  • take操作符

如果我們只想要最多5個結果:

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(url -> getTitle(url))  
    .filter(title -> title != null)  
    .take(5)  
    .subscribe(title -> System.out.println(title)); 
  • doOnNext操作符

如果我們想在列印之前,把每個標題儲存到磁碟:

query("Hello, world!")  
    .flatMap(urls -> Observable.from(urls))  
    .flatMap(url -> getTitle(url))  
    .filter(title -> title != null)  
    .take(5)  
    .doOnNext(title -> saveTitle(title))  
    .subscribe(title -> System.out.println(title)); 

5.其他的操作符

  • 用於建立Observable的操作符:
  • 變換操作:這些操作符可用於對Observable發射的資料進行變換
  • 過濾操作:這些操作符用於從Observable發射的資料中進行選擇
  • 組合操作:用於將多個Observable組合成一個單一的Observable
  • 錯誤處理:這些操作符用於從錯誤通知中恢復
  • 輔助操作:用於處理Observable的操作符
  • 條件和布林操作:這些操作符可用於單個或多個數據項,也可用於Observable
  • 算術和聚合操作:可用於整個資料序列
  • 連線操作:一些有精確可控的訂閱行為的特殊Observable
  • 轉換操作:
  • 【注意:操作符決策樹】
  1. 列表內容
    Create — 通過呼叫觀察者的方法從頭建立一個Observable
    Defer — 在觀察者訂閱之前不建立這個Observable,為每一個觀察者建立一個新的Observable
    Empty/Never/Throw — 建立行為受限的特殊Observable
    From — 將其它的物件或資料結構轉換為Observable
    Interval — 建立一個定時發射整數序列的Observable
    Just — 將物件或者物件集合轉換為一個會發射這些物件的Observable
    Range — 建立發射指定範圍的整數序列的Observable
    Repeat — 建立重複發射特定的資料或資料序列的Observable
    Start — 建立發射一個函式的返回值的Observable
    Timer — 建立在一個指定的延遲之後發射單個數據的Observable
  2. 變換操作
    Buffer — 快取,可以簡單的理解為快取,它定期從Observable收集資料到一個集合,然後把這些資料集合打包發射,而不是一次發射一個
    FlatMap — 扁平對映,將Observable發射的資料變換為Observables集合,然後將這些Observable發射的資料平坦化的放進一個單獨的Observable,可以認為是一個將巢狀的資料結構展開的過程。
    GroupBy — 分組,將原來的Observable分拆為Observable集合,將原始Observable發射的資料按Key分組,每一個Observable發射一組不同的資料
    Map — 對映,通過對序列的每一項都應用一個函式變換Observable發射的資料,實質是對序列中的每一項執行一個函式,函式的引數就是這個資料項
    Scan — 掃描,對Observable發射的每一項資料應用一個函式,然後按順序依次發射這些值
  3. 過濾操作
    Debounce — 只有在空閒了一段時間後才發射資料,通俗的說,就是如果一段時間沒有操作,就執行一次操作
    Distinct — 去重,過濾掉重複資料項
    ElementAt — 取值,取特定位置的資料項
    Filter — 過濾,過濾掉沒有通過謂詞測試的資料項,只發射通過測試的
    First — 首項,只發射滿足條件的第一條資料
    IgnoreElements — 忽略所有的資料,只保留終止通知(onError或onCompleted)
    Last — 末項,只發射最後一條資料
    Sample — 取樣,定期發射最新的資料,等於是資料抽樣,有的實現裡叫ThrottleFirst
    Skip — 跳過前面的若干項資料
    SkipLast — 跳過後面的若干項資料
    Take — 只保留前面的若干項資料
    TakeLast — 只保留後面的若干項資料
  4. 組合操作
    And/Then/When — 通過模式(And條件)和計劃(Then次序)組合兩個或多個Observable發射的資料集
    CombineLatest — 當兩個Observables中的任何一個發射了一個數據時,通過一個指定的函式組合每個Observable發射的最新資料(一共兩個資料),然後發射這個函式的結果
    Join — 無論何時,如果一個Observable發射了一個數據項,只要在另一個Observable發射的資料項定義的時間視窗內,就將兩個Observable發射的資料合併發射
    Merge — 將兩個Observable發射的資料組合併成一個
    StartWith — 在發射原來的Observable的資料序列之前,先發射一個指定的資料序列或資料項
    Switch — 將一個發射Observable序列的Observable轉換為這樣一個Observable:它逐個發射那些Observable最近發射的資料
    Zip — 打包,使用一個指定的函式將多個Observable發射的資料組合在一起,然後將這個函式的結果作為單項資料發射
  5. 錯誤處理
    Catch — 捕獲,繼續序列操作,將錯誤替換為正常的資料,從onError通知中恢復
    Retry — 重試,如果Observable發射了一個錯誤通知,重新訂閱它,期待它正常終止

  6. 輔助操作
    Delay — 延遲一段時間發射結果資料
    Do — 註冊一個動作佔用一些Observable的生命週期事件,相當於Mock某個操作
    Materialize/Dematerialize — 將發射的資料和通知都當做資料發射,或者反過來
    ObserveOn — 指定觀察者觀察Observable的排程程式(工作執行緒)
    Serialize — 強制Observable按次序發射資料並且功能是有效的
    Subscribe — 收到Observable發射的資料和通知後執行的操作
    SubscribeOn — 指定Observable應該在哪個排程程式上執行
    TimeInterval — 將一個Observable轉換為發射兩個資料之間所耗費時間的Observable
    Timeout — 新增超時機制,如果過了指定的一段時間沒有發射資料,就發射一個錯誤通知
    Timestamp — 給Observable發射的每個資料項新增一個時間戳
    Using — 建立一個只在Observable的生命週期記憶體在的一次性資源

  7. 條件和布林操作
    All — 判斷Observable發射的所有的資料項是否都滿足某個條件
    Amb — 給定多個Observable,只讓第一個發射資料的Observable發射全部資料
    Contains — 判斷Observable是否會發射一個指定的資料項
    DefaultIfEmpty — 發射來自原始Observable的資料,如果原始Observable沒有發射資料,就發射一個預設資料
    SequenceEqual — 判斷兩個Observable是否按相同的資料序列
    SkipUntil — 丟棄原始Observable發射的資料,直到第二個Observable發射了一個數據,然後發射原始Observable的剩餘資料
    SkipWhile — 丟棄原始Observable發射的資料,直到一個特定的條件為假,然後發射原始Observable剩餘的資料
    TakeUntil — 發射來自原始Observable的資料,直到第二個Observable發射了一個數據或一個通知
    TakeWhile — 發射原始Observable的資料,直到一個特定的條件為真,然後跳過剩餘的資料
  8. 算術和聚合操作
    Average — 計算Observable發射的資料序列的平均值,然後發射這個結果
    Concat — 不交錯的連線多個Observable的資料
    Count — 計算Observable發射的資料個數,然後發射這個結果
    Max — 計算併發射資料序列的最大值
    Min — 計算併發射資料序列的最小值
    Reduce — 按順序對資料序列的每一個應用某個函式,然後返回這個值
    Sum — 計算併發射資料序列的和
  9. 連線操作
    Connect — 指示一個可連線的Observable開始發射資料給訂閱者
    Publish — 將一個普通的Observable轉換為可連線的
    RefCount — 使一個可連線的Observable表現得像一個普通的Observable
    Replay — 確保所有的觀察者收到同樣的資料序列,即使他們在Observable開始發射資料之後才訂閱
  10. 轉換操作
    To — 將Observable轉換為其它的物件或資料結構
    Blocking 阻塞Observable的操作符
  11. 【注意:操作符決策樹】
    直接建立一個Observable(建立操作)
    組合多個Observable(組合操作)
    對Observable發射的資料執行變換操作(變換操作)
    從Observable發射的資料中取特定的值(過濾操作)
    轉發Observable的部分值(條件/布林/過濾操作)
    對Observable發射的資料序列求值(算術/聚合操作)

回到頂部

相關推薦

Rxjava2.操作符

參考地址 本文主要分為: 寫下本文原因: 加深印象+理解+後期鞏固 1.準備工作 假如我有這樣一個方法: 這個方法根據傳入的字串返回一個網站的url列表結果: Observable<List<Str

RxJava十一defer操作符實現程式碼支援鏈式呼叫

RxJava系列文章目錄導讀: 一、前言 現在越來越多Android開發者使用到RxJava,在Android使用RxJava主要有如下好處: 1,輕鬆切換執行緒。以前我們切換執行緒主要使用Handler等手段來做。 2,輕鬆解決回撥的巢狀問題。

LA 3211 飛機調度2—SAT

選擇 排列 tps pri abs true nbsp queue 需要 https://vjudge.net/problem/UVALive-3211 題意: 有n架飛機需要著陸,每架飛機都可以選擇“早著陸”和“晚著陸”

POJ 3905 Perfect Election2-sat

pop data- let itl dsm sun add void space POJ 3905 Perfect Election 題目鏈接 思路:非常裸的2-sat,就依據題意建邊就可以 代碼: #include <cstdio> #inclu

Spring Security入門2-3HttpSecurity的使用

登錄 一個 最終 指定 ebs row pat ati 是我 到目前為止我們的 SecurityConfig 只包含了關於如何驗證我們的用戶的信息。 Spring Security怎麽知道我們想對所有的用戶進行驗證?Spring Security怎麽知道我們需要支持基於表單

Python學習筆記2.1函數參數練習

col python學習 nbsp cnblogs print item info inf -- 關鍵字參數 和 命名關鍵字參數 # -*- coding: utf-8 -*- def print_scores(**kw): print(‘

zabbix安裝2.4

zabbix相關鏈接zabbix官網:https://www.zabbix.com/zabbix軟件下載:https://www.zabbix.com/downloadZabbix 文檔:https://www.zabbix.com/documentation/2.4/manual/installation/

Vue.js2.x之計算屬性

眼睛 猜想 官網文檔 data ctype 小結 isp def 直接 昨天看完大神的文章後,深感慚愧,硬著頭皮繼續看官網文檔,然而這真的沒是沒辦法,介紹的實在有些敷衍: 1)、計算屬性:也不說下computed是計算屬性關鍵詞,vm實例是可以像代理data一樣代理comp

Python命令行加TAB補全2.6

python 自動補全 tab 首先,要找到Python的路徑[[email protected]/* */ python2.6]$ python Python 2.6.6 (r266:84292, Nov 22 2013, 12:16:22) [GCC 4.4.7 20120313

centos7使用cobbler2.8批量部署

centos cobbler 一、 批量部署操作系統的前提要想批量部署操作系統,得具備以下條件:客戶機支持pxe網絡引導服務器端和客戶端建立網絡通信(DHCP)服務器端要有可供客戶機開機引導的引導文件服務器端的可引導文件還必須能傳遞到客戶機(TFTP)客戶機無人值守安裝包括安裝定制的軟件或服務(

深入理解計算機系統2.4------整數的表示無符號編碼和補碼編碼

class 映射 們的 c語言 正數 裏的 小例子 負數 類型   上一篇博客我們主要介紹了布爾代數和C語言當中的幾個運算符。那麽這一篇博客我們主要介紹在計算機中整數是如何表示的,諸如我們在編碼過程中遇到的對數據類型進行強制轉換可能會得到意想不到的結果在這篇博客裏你會得到解

UVALive 3211 : Now or later 2-SAT

back using cto b+ include mark std () val 題目鏈接 題意及題解參見lrj訓練指南 #include<bits/stdc++.h> using namespace std; const int maxn=4e3+5;

大數據Hadoop學習之搭建Hadoop平臺2.1

穩定版 發的 log tar sshd scheduler 文件夾 三種 rest    關於大數據,一看就懂,一懂就懵。 一、簡介   Hadoop的平臺搭建,設置為三種搭建方式,第一種是“單節點安裝”,這種安裝方式最為簡單,但是並沒有展示出Hadoop的技術優勢,適

怎麽樣實現遠程訪問交換機2,路由

2給2臺服務器配置IP,掩碼,網關打開交換機,進入全局模式,分別給每臺交換機配置VLAN;設置VTY遠程訪問密碼;(交換機的默認IP ip default-gateway (192.168.1.254(這是根據你自己說設的VLAN決定的),每臺機都有自己的默認IP(所連交換機的VLAN))。怎麽樣實現遠程訪問

Beta 沖刺 2/7

實戰 提取方法 實現 src 規範 年終總結 一周內 https 提取 前言 我們居然又沖刺了·二 團隊代碼管理github 站立會議 隊名:PMS 530雨勤(組長) 過去兩天完成了哪些任務 了解OpenCV下的視頻參數及其調用方法 初步編碼 接下來的計劃

POJ 3683 Priest John's Busiest Day2-sat

ant log ret ims esp top gin csdn can POJ 3683 Priest John‘s Busiest Day id=3683">題目鏈接 題意:給定幾個時間,si, ti, di每一

python之函數的進階2-1

加載 gif pre span 進行 文件 chang ret 16px 動態參數: 一,*args:args是元祖,它包含了所有的位置參數。 1,第一種形參中只含*args。 def func(*args): print(*args,type(args)) f

【BZOJ1997】Planar2-sat

tin efi -s com 開始 ++ blog ble body 【BZOJ1997】Planar(2-sat) 題面 BZOJ 題解 很久沒做過\(2-sat\)了 今天一見,很果斷的就來切 這題不難呀 但是有個玄學問題: 平面圖的性質:邊數\(m\)的最大值為\(3

powershell修改文件中某個字符串-replace操作符

字符 是個 腳本執行 pos -s get replace lac 結果 使用-replace操作符 test.txt文件內容 1234hello worldaaa "hhh" fwdbz test.ps1腳本文件 $(Get-Content E:\demo\test.t

【大話存儲II】學習筆記2, SSD

ssd 中一 logs 什麽是 直接 範圍 平衡 機械 ive 我們知道機械硬盤最大的缺點在於,尋道時間比較長,也就是不適合隨機小塊IO。所以這幾年固態存儲大行其道,因為它對任何地址訪問的開銷都相等,節省了機械尋道時間,所以隨機IO性能很好。 當前的SSD硬盤,單塊SSD的