RxJava 學習筆記<八> 譯 Transformation of sequences

 Transformation of sequences

在本章中,咱們將看到改變數據格式的方法。在現實世界中,observable 能夠是任何類型的。數據的格式已是咱們想要的格式,這是不常見的。更有可能的狀況是,這些值須要擴展、裁剪、評估或簡單地替換爲其餘值。ios

這將由 oprations 的三個基本類別來完成。map 和 flatMap 是第三類的基本方法。在文獻中,您經常會發現它們被稱爲「bind」,至於緣由超出了本指南的範圍。git

Ana(morphism) T --> Observable<T>
Cata(morphism) Observable<T> --> T
Bind Observable<T1> --> Observable<T2>程序員

在最後一章中,爲了方便起見,咱們介紹了 Subscriber 的一個實現。咱們將在本章的示例中繼續使用它。github

map

轉換的基本方法是 map(在相似由SQL啓發的系統(如LINQ)中也稱爲「SELECT」)。它接受一個轉換函數,它接受一個項並返回任何類型的新項。返回的可觀測值由轉換函數返回的值組成。編程

在第一個例子中,咱們將取一個整數序列,並將它們增長3。異步

輸出:函數式編程

這就是 map 作的事情,例如經過使用 Observable.range(3,4)。在下面,咱們將作一些更實際的事情。生產者將像許多 UI 一般所作的那樣,以字符串的形式發出數值,而後使用map將它們轉換爲更可處理的整數格式。函數

輸出:spa

這種轉換很是簡單,咱們也能夠在訂閱方進行,但這將是一種糟糕的責任劃分。在開發生產者方面時,您但願以儘量簡潔和最方便的方式呈現事物。你不會轉儲原始數據,讓消費者本身去發現。在咱們的示例中,既然咱們說API生成整數,它就應該這樣作。Transfomation操做符容許咱們將初始序列轉換爲咱們想要公開的API。調試

cast and ofType

cast 是將 item 轉換爲另外一種類型的簡寫。若是您有一個 Observable<Object>,您知道它只會發出T類型的值,那麼在lambda函數中強制轉換可觀察到的值比進行強制轉換要簡單得多。

輸出:

若是不能將全部項強制轉換爲指定類型,則強制轉換方法將失敗。

輸出:

若是您但願忽略此類狀況,則可使用ofType方法。這將過濾沒法強制轉換的項,而後將序列轉換爲所需的類型。

輸出:

timestamp and timeInterval

timestamp 和 timeInterval 方法使咱們可以用有關序列的異步性質的信息來豐富咱們的值。timestamp將值轉換 Timestamped<T> 類型,該類型包含原始值,以及發出事件時的時間戳

public final Observable<Timestamped<T>> timestamp()

這裏是一個例子:

輸出:

時間戳使咱們能夠看到這些項大約是隔100毫秒發出的(Java對此幾乎沒有提供保證)。

若是咱們更感興趣的是自上一項以後已通過去了多少時間,而不是發出項目的絕對時刻,咱們可使用timeInterval方法

public final Observable<TimeInterval<T>> timeInterval()

按照與前面相同的順序使用timeInterval:

輸出:

timestamp 和TimeInterval捕獲的信息對於日誌記錄和調試很是有用。它是Rx獲取序列異步性信息的一種方法。

materialize and dematerialize

materialize 對於日誌記錄也頗有用,materialize 將序列轉換爲它的元數據表示形式。

通知類型能夠表示任何事件,即值的釋放、錯誤或完成。注意,在上面的圖中,「onCompleted」的發射並不意味着序列的結束,由於序列其實是隨後結束的。下面是一個例子

輸出:

Notification type包含用於肯定事件類型以及攜帶值或Throwable(若是有的話)的方法。

dematerialize 將逆轉 materialize 的效果,使 materialized observable 返回到它的正常形式。

flatMap

map取一個值,而後返回另外一個值,替換順序爲一對一的項。flatMap 將用任意數量的項替換項目,包括零項或無窮項。flatMap 的轉換方法從源 observable 中獲取值,並對每一個值返回一個新的 observable,發射新值。

由 flatMap 返回的可觀測值將發出由轉換函數產生的全部可觀測值發出的全部值。來自同一可觀測值的值將是有序的,但它們可能與來自其餘可觀測值的值交織在一塊兒。

讓咱們從一個簡單的例子開始,其中 FlapMap 應用於一個具備單個值的 observable ,將發出一個單獨的值。FlapMap將把它轉換爲一個即0到2之間的範圍的 observable。這個可觀測值是在最終的可觀測值中發射出來的。

輸出:

當 flatMap 應用於多個值的 observable ,每一個值將產生一個新的 observable , values 將發出一、2和3。獲得的 observable 將分別發出值[0]、[0,1]和[0,1,2]。這些值將被平鋪在一塊兒,造成一個可觀察到的值:由FlapMap返回的值。

輸出:

與 map 很是類似,platMap 的輸入和輸出類型能夠自由地有所不一樣。在下一個示例中,咱們將把整數轉換爲字符。

輸出:

雖然每一個值都必須產生一個可觀察的值,可是沒有什麼能夠阻止這個可觀察到的值是空的。咱們能夠用它來過濾序列,同時對其進行轉換。

輸出:

此示例將致使打印整個字母表而不會出錯,即便初始範圍超過字母表的範圍。

到目前爲止,在咱們的flatMap 示例中,值按順序排列:首先是來自第一個可觀測值的全部值,而後是來自第二個可觀測值的全部值。雖然這彷佛很直觀,特別是在來自同步環境時,但須要注意的是,狀況並不老是如此。FlapMap返回的可觀察值一旦可用就會發出值。在咱們的例子中,全部的觀測值都是同步準備好的。爲了證實這一點,咱們使用區間方法構造異步觀測值。

輸出:

咱們從值100和150開始,將它們用做在 FlapMap 中建立的異步觀測值的間隔期間。由於間隔發出數字1,2,3...在這兩種狀況下,爲了更好地區分這兩個可觀察到的值,咱們用每一個可觀察到的操做所依據的間隔時間替換這些值。

咱們能夠看到,這兩個觀測值交織在一塊兒。

concatMap

儘管在函數式編程中,FlapMap與一個很是常見的操做符同名,但咱們發現它的行爲並不徹底像函數式程序員所指望的那樣。有一個運算符不會交錯序列,名爲contatMap,由於它與咱們稍後將看到的conat運算符相關。

輸出:

咱們能夠在輸出中看到這兩個序列是分開的。請注意,contatMap操做符只適用於終止序列:在當前序列終止以前,它不能移動到下一個序列。因爲這個緣由,咱們不得不用Take來限制區間的無窮序列。

flatMapIterable

flatMap 和 concatMap 將由它們的選擇器函數生成的一系列可觀察到的東西平鋪成一個可觀察的東西。咱們還可使用FlapMapIterable來平抑一個迭代序列。這相似於 flatMap ,只有咱們的選擇器函數建立迭代。

若是取代 Observable.range ,咱們可能寫下面的迭代器

輸出:

正如預期的那樣,咱們建立的三個迭代在一個可觀察的序列中被壓平(flattened)。

做爲一名Rx開發人員,建議您將數據表示爲可觀察序列,並避免將可觀測序列與迭代序列相混合。可是,當您的數據已經採用集合的格式時(例如,由於標準Java操做會這樣返回它們),只使用它們而不首先轉換它們可能會更簡單或更快。FlapMapIterable還消除了選擇交錯與否的須要:FlapMapIterable不會交錯,就像您指望從同步FlapMap中獲得的同樣。

還有第二個重載,它容許您將可迭代中的每一個值與生成可迭代的值組合在一塊兒。

輸出:

在這裏,咱們將迭代範圍中的每一個值乘以播種範圍的值:[1*1]、[1*二、2*2]、[1*三、2*三、3*3]。

Java缺少對其標準集合進行映射的方法。所以,在種子值消失以前不可能轉換可迭代值(這裏是i->範圍(1,i)中的i)。在這裏,咱們的可迭代僅僅是一個列表,因此咱們能夠在返回它以前修改它。可是,若是咱們的可迭代不是一個集合,咱們將不得不本身實現一個迭代映射,或者手動將修改後的值收集到一個新的集合中並返回它。這個重載的FlapMapIterable使咱們沒必要將這種醜陋插入到管道的中間。

懶惰的概念在Java中並不常見,所以您可能會對哪些類型的可迭代不是集合感到困惑。爲了舉例說明,請考慮下面的可迭代性,它懶散地生成一個範圍。它容許咱們經過計算上一個值的下一個值來迭代一個範圍。這樣,咱們節省了存儲整個範圍的內存。

輸出:

原文連接:

https://github.com/Froussios/Intro-To-RxJava/blob/master/Part%202%20-%20Sequence%20Basics/5.%20Transformation%20of%20sequences.md

相關文章
相關標籤/搜索