Rxjava操作符講解(2)Transforming 變換操作符

之前沒有了解過Rxjava的童鞋铣卡,建議先閱讀《Rxjava 從入門到開發(fā)》這篇文章伸但,對入門比較有幫助眯牧。

map操作符

作用:通過call函數(shù)根據(jù)函數(shù)Func1<T,K>把T轉(zhuǎn)換為K

List<Student> students=new ArrayList<>();
    Student stuent=new Student();
    stuent.setName("小一");
    Student s1=new Student();
    s1.setName("小二");
    students.add(stuent);
    students.add(s1);
    subscription=Observable.from(students).map(new Func1<Student, String>() {

        @Override
        public String call(Student student) {
            return student.getName();
        }
    }).subscribe(new Action1<String>() {
        @Override
        public void call(String s) {
            Logger.i("MapOperation : "+s);
        }
    });

輸出結(jié)果:

例子說明:通過map操作符糠睡,我們把輸入的Student對象轉(zhuǎn)換成了String變量脏毯,然后遍歷輸出。

flag map操作符

作用:對序列的每一項(xiàng)通過call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過操作符轉(zhuǎn)換為K

Observable.just(10, 20, 30).flatMap(new Func1<Integer, Observable<Integer>>() {
        @Override
        public Observable<Integer> call(Integer integer) {
            //10的延遲執(zhí)行時(shí)間為200毫秒霜瘪、20和30的延遲執(zhí)行時(shí)間為180毫秒
            int delay = 200;
            if (integer > 10)
                delay = 180;

            return Observable.from(new Integer[]{integer, integer / 2}).delay(delay, TimeUnit.MILLISECONDS);
        }
    }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Integer>() {
        @Override
        public void call(Integer integer) {
            System.out.println("flatMap Next:" + integer);
        }
    });

輸出結(jié)果:

例子說明:輸入數(shù)字10珠插,20,30通過操作符from和delay輸出颖对,這里要注意的是捻撑,輸出結(jié)果已經(jīng)出現(xiàn)了亂序,即沒有按照10缤底,5顾患;20,10个唧;30江解,15的順序輸出。

concatMap操作符

作用:對序列的每一項(xiàng)通過call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過操作符轉(zhuǎn)換為K徙歼,相對于flatmap可以保證輸出順序一致

Observable.just(10, 20, 30).concatMap(new Func1<Integer, Observable<Integer>>() {
        @Override
        public Observable<Integer> call(Integer integer) {
            //10的延遲執(zhí)行時(shí)間為200毫秒犁河、20和30的延遲執(zhí)行時(shí)間為180毫秒
            int delay = 200;
            if (integer > 10)
                delay = 180;

            return Observable.from(new Integer[]{integer, integer / 2}).delay(delay, TimeUnit.MILLISECONDS);
        }
    }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Integer>() {
        @Override
        public void call(Integer integer) {
            System.out.println("concatMap Next:" + integer);
        }
    });

輸出結(jié)果:

例子說明:輸入數(shù)字10鳖枕,20,30通過操作符from和delay輸出桨螺,這里要注意的是耕魄,輸出結(jié)果沒有出現(xiàn)亂序

switchMap操作符

作用:對序列的每一項(xiàng)通過call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過操作符轉(zhuǎn)換為K,若結(jié)果k1,k2同時(shí)出現(xiàn)則則會(huì)保留最新的k2彭谁,丟棄k1

Observable.just(10, 20, 30).switchMap(new Func1<Integer, Observable<Integer>>() {
        @Override
        public Observable<Integer> call(Integer integer) {
            //10的延遲執(zhí)行時(shí)間為200毫秒吸奴、20和30的延遲執(zhí)行時(shí)間為180毫秒
            int delay = 200;
            if (integer > 10)
                delay = 180;

            return Observable.from(new Integer[]{integer, integer / 2}).delay(delay, TimeUnit.MILLISECONDS);
        }
    }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Integer>() {
        @Override
        public void call(Integer integer) {
            System.out.println("switchMap Next:" + integer);
        }
    });

輸出結(jié)果:

例子說明:輸入數(shù)字10,20缠局,30通過操作符from和delay輸出则奥,但是由于switchmap操作符的作用,10的輸出被20覆蓋狭园,20的輸出結(jié)果被30覆蓋读处,故最后只有30,15輸出唱矛。

以上demo 出自Android RxJava使用介紹(三) RxJava的操作符罚舱,最后總結(jié)下map,flatmap绎谦,contactmap管闷,switchmap的使用場景區(qū)別:map用于不需要通過操作符就可以完成的轉(zhuǎn)換,flatmap用于需要通過操作符才可以轉(zhuǎn)換的操作窃肠,但是輸出結(jié)果可能會(huì)是亂序包个,contactmap的作用在flatmap的基礎(chǔ)上保證輸出結(jié)果按照輸入順序輸出,switchmap的作用在flatmap的基礎(chǔ)上冤留,對輸出結(jié)果若同時(shí)發(fā)生碧囊,只會(huì)保證最新結(jié)果而放棄舊數(shù)據(jù)。

Scan操作符

作用:連續(xù)地對數(shù)據(jù)序列的每一項(xiàng)應(yīng)用一個(gè)函數(shù)纤怒,然后連續(xù)發(fā)射結(jié)果

    Integer numbers[]={1,2,3,4,5,};
    Observable observable=Observable.from(numbers);
    subscription=observable.scan(new Func2<Integer,Integer,Integer>() {
                @Override
                public Integer call(Integer sum, Integer item) {
                    System.out.println(" sum: "+sum+"  item: "+item);
                    return sum+item;
                }
            })
            .subscribe(new Action1() {
                @Override
                public void call(Object o) {
                    System.out.println(" number: "+o);
                }
            });
    SubscriptionManager.setSubscription(subscription);

輸出結(jié)果:

例子說明:這里要注意的是變量sum等于輸入數(shù)相加糯而,item為某項(xiàng)輸入,例如:現(xiàn)在輸入的是3泊窘,即item為3熄驼,sum則為1和2相加的結(jié)果,最后返回的是3+3等6州既,下一步輸入item為4谜洽,則sum為6萝映,接下來返回的便是6+4的結(jié)果吴叶。

groupBy操作符

作用:可以對輸入的數(shù)據(jù)根據(jù)自定義類型分組

Observable.create(new Observable.OnSubscribe<Integer>() {
        @Override
        public void call(Subscriber<? super Integer> subscriber) {
            for(int i=0;i<6;i++){
                int number=random.nextInt(10);
                System.out.println("key: " + number);
                subscriber.onNext(number);
            }
        }
    }).groupBy(new Func1<Integer, String>() {
        @Override
        public String call(Integer value) {
            return value % 2 == 0 ? "偶數(shù)" : "奇數(shù)";
        }
    }).subscribe(new Action1<GroupedObservable<String, Integer>>() {
        @Override
        public void call(final GroupedObservable<String, Integer> stringIntegerGroupedObservable) {
            stringIntegerGroupedObservable.subscribe(new Action1<Integer>() {
                @Override
                public void call(Integer integer) {
                    System.out.println("key:" + stringIntegerGroupedObservable.getKey() +", value:" + integer);
                }
            });
        }
    });

輸出結(jié)果:

例子說明:輸入六個(gè)隨機(jī)數(shù)8,1序臂,2蚌卤,8实束,7,8逊彭,結(jié)果我原以為數(shù)據(jù)會(huì)先輸出偶數(shù)項(xiàng)咸灿,再輸出奇數(shù)項(xiàng),但是結(jié)果卻是輸出數(shù)據(jù)的順序和輸入一致侮叮,但是通過GroupedObservable.getkey 方法可以獲取數(shù)據(jù)所屬分類避矢。另外這里需要注意的是:groupBy將原始Observable分解為一個(gè)發(fā)射多個(gè)GroupedObservable的Observable,一旦有訂閱囊榜,每個(gè)GroupedObservable就開始緩存數(shù)據(jù)审胸。因此,如果你忽略這些GroupedObservable中的任何一個(gè)卸勺,這個(gè)緩存可能形成一個(gè)潛在的內(nèi)存泄露砂沛。因此,如果你不想觀察曙求,也不要忽略GroupedObservable碍庵。你應(yīng)該使用像take(0)這樣會(huì)丟棄自己的緩存的操作符。

Buffer操作符

作用:定期收集Observable的數(shù)據(jù)放進(jìn)一個(gè)數(shù)據(jù)包裹悟狱,然后發(fā)射這些數(shù)據(jù)包裹静浴,而不是一次發(fā)射一個(gè)值。

     Observable.create(new Observable.OnSubscribe<String>() {

        @Override
        public void call(Subscriber<? super String> subscriber) {
                final String[] names = {"小-", "小二", "小三", "小四", "小五"};
                Random random = new Random();
                if(subscriber.isUnsubscribed()){
                    return;
                }
                do {
                    String name = names[random.nextInt(names.length)];
                    subscriber.onNext(name);
                try {
                    Thread.sleep(1000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                } while (true);
        }
    }).subscribeOn(Schedulers.io()).buffer(2,TimeUnit.SECONDS).subscribe(new Action1<List<String>>() {
        @Override
        public void call(List<String> strings) {
            System.out.println("開始兩秒點(diǎn)一次名字...");
            for (String name:strings) {
                System.out.println("name: "+name);
            }
        }
    });

輸出結(jié)果:

例子說明:create操作符里面一直在做每隔1秒就發(fā)送一個(gè)隨機(jī)名字的操作挤渐,通過buffer操作符可以實(shí)現(xiàn)每隔2秒輸出一組名字马绝。

Window操作符

作用:和buffer類似作用類似,但是輸出的是Observable而不是具體數(shù)據(jù)

Observable.interval(1, TimeUnit.SECONDS).take(10).
            window(2,TimeUnit.SECONDS).subscribe(new Action1<Observable<Long>>() {
        @Override
        public void call(Observable<Long> longObservable) {

            System.out.println("每隔兩秒打印.....");
            longObservable.subscribe(new Action1<Long>() {
                @Override
                public void call(Long aLong) {
                    System.out.println("currentNumber: "+aLong);
                }
            });
        }
    });

輸出結(jié)果:

例子說明:interval操作符表示按照順序和預(yù)期時(shí)間輸出一個(gè)0-n的數(shù)列挣菲,例如:0富稻,1,2...n, take操作符表示截取前n個(gè)結(jié)果集白胀,在例子中就是截取interval操作符輸出的0-9共10個(gè)數(shù)椭赋,** window操作符作用和buffer差不多,不同的是buffer輸出具體的數(shù)值或杠,但是Window輸出的Observable哪怔,需要再進(jìn)一步訂閱才能輸出具體數(shù)值**。

Cast操作符

作用:對數(shù)據(jù)進(jìn)行強(qiáng)轉(zhuǎn)類型

但是實(shí)際使用中本人發(fā)現(xiàn)僅僅能用于對輸入數(shù)據(jù)的類型判斷是否符合預(yù)期

    String[] strs=new String[]{"1","2","3","4","5"};
    subscription=Observable.from(strs).observeOn(Schedulers.io()).cast(Integer.class).subscribe(new Action1<Integer>() {
        @Override
        public void call(Integer integer) {
            System.out.println("integer: " + integer);
        }
    }, new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            throwable.printStackTrace();
        }
    });

輸出結(jié)果:

例子說明:輸入類型正確則輸出源數(shù)據(jù)向抢,如果輸入數(shù)據(jù)某項(xiàng)內(nèi)容類型不正確认境,則報(bào)錯(cuò)。

以上便是變換操作符的主要內(nèi)容了挟鸠。有啥問題歡迎大家留言交流下??叉信,下篇文章再說說過濾操作符歡迎關(guān)注。

附錄:
文章demo

參考:
ReactiveX/RxJava文檔中文版

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末艘希,一起剝皮案震驚了整個(gè)濱河市硼身,隨后出現(xiàn)的幾起案子硅急,更是在濱河造成了極大的恐慌,老刑警劉巖佳遂,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件营袜,死亡現(xiàn)場離奇詭異,居然都是意外死亡丑罪,警方通過查閱死者的電腦和手機(jī)荚板,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吩屹,“玉大人啸驯,你說我怎么就攤上這事∷盥停” “怎么了罚斗?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宅楞。 經(jīng)常有香客問我针姿,道長,這世上最難降的妖魔是什么厌衙? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任距淫,我火速辦了婚禮,結(jié)果婚禮上婶希,老公的妹妹穿的比我還像新娘榕暇。我一直安慰自己,他們只是感情好喻杈,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布彤枢。 她就那樣靜靜地躺著,像睡著了一般筒饰。 火紅的嫁衣襯著肌膚如雪缴啡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天瓷们,我揣著相機(jī)與錄音业栅,去河邊找鬼。 笑死谬晕,一個(gè)胖子當(dāng)著我的面吹牛碘裕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播攒钳,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼帮孔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了夕玩?” 一聲冷哼從身側(cè)響起你弦,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎燎孟,沒想到半個(gè)月后禽作,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡揩页,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年旷偿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爆侣。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萍程,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兔仰,到底是詐尸還是另有隱情茫负,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布乎赴,位于F島的核電站忍法,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏榕吼。R本人自食惡果不足惜饿序,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望羹蚣。 院中可真熱鬧原探,春花似錦、人聲如沸顽素。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胁出。三九已至离唬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間划鸽,已是汗流浹背输莺。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裸诽,地道東北人嫂用。 一個(gè)月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像丈冬,于是被迫代替她去往敵國和親嘱函。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 本篇文章介主要紹RxJava中操作符是以函數(shù)作為基本單位埂蕊,與響應(yīng)式編程作為結(jié)合使用的往弓,對什么是操作疏唾、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,867評論 0 10
  • 前言 按照官方的分類,操作符大致分為以下幾種: Creating Observables(Observable的創(chuàng)...
    小玉1991閱讀 1,052評論 0 1
  • 創(chuàng)建操作 用于創(chuàng)建Observable的操作符Create通過調(diào)用觀察者的方法從頭創(chuàng)建一個(gè)ObservableEm...
    rkua閱讀 1,836評論 0 1
  • 注:只包含標(biāo)準(zhǔn)包中的操作符函似,用于個(gè)人學(xué)習(xí)及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 2,199評論 2 8
  • 作者: maplejaw本篇只解析標(biāo)準(zhǔn)包中的操作符槐脏。對于擴(kuò)展包,由于使用率較低撇寞,如有需求顿天,請讀者自行查閱文檔。 創(chuàng)...
    maplejaw_閱讀 45,698評論 8 93