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

之前沒(méi)有了解過(guò)Rxjava的童鞋,建議先閱讀《Rxjava 從入門到開發(fā)》這篇文章,對(duì)入門比較有幫助。

map操作符

作用:通過(guò)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é)果:

例子說(shuō)明:通過(guò)map操作符,我們把輸入的Student對(duì)象轉(zhuǎn)換成了String變量,然后遍歷輸出。

flag map操作符

作用:對(duì)序列的每一項(xiàng)通過(guò)call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過(guò)操作符轉(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é)果:

例子說(shuō)明:輸入數(shù)字10,20,30通過(guò)操作符from和delay輸出,這里要注意的是,輸出結(jié)果已經(jīng)出現(xiàn)了亂序,即沒(méi)有按照10,5;20,10;30,15的順序輸出。

concatMap操作符

作用:對(duì)序列的每一項(xiàng)通過(guò)call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過(guò)操作符轉(zhuǎn)換為K,相對(duì)于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é)果:

例子說(shuō)明:輸入數(shù)字10,20,30通過(guò)操作符from和delay輸出,這里要注意的是,輸出結(jié)果沒(méi)有出現(xiàn)亂序

switchMap操作符

作用:對(duì)序列的每一項(xiàng)通過(guò)call函數(shù)根據(jù)函數(shù)Func1<T,Observable<K>>把T通過(guò)操作符轉(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é)果:

例子說(shuō)明:輸入數(shù)字10,20,30通過(guò)操作符from和delay輸出,但是由于switchmap操作符的作用,10的輸出被20覆蓋,20的輸出結(jié)果被30覆蓋,故最后只有30,15輸出。

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

Scan操作符

作用:連續(xù)地對(duì)數(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é)果:

例子說(shuō)明:這里要注意的是變量sum等于輸入數(shù)相加,item為某項(xiàng)輸入,例如:現(xiàn)在輸入的是3,即item為3,sum則為1和2相加的結(jié)果,最后返回的是3+3等6,下一步輸入item為4,則sum為6,接下來(lái)返回的便是6+4的結(jié)果。

groupBy操作符

作用:可以對(duì)輸入的數(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é)果:

例子說(shuō)明:輸入六個(gè)隨機(jī)數(shù)8,1,2,8,7,8,結(jié)果我原以為數(shù)據(jù)會(huì)先輸出偶數(shù)項(xiàng),再輸出奇數(shù)項(xiàng),但是結(jié)果卻是輸出數(shù)據(jù)的順序和輸入一致,但是通過(guò)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é)果:

例子說(shuō)明:create操作符里面一直在做每隔1秒就發(fā)送一個(gè)隨機(jī)名字的操作,通過(guò)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é)果:

例子說(shuō)明: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操作符

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

但是實(shí)際使用中本人發(fā)現(xiàn)僅僅能用于對(duì)輸入數(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é)果:

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

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

附錄:
文章demo

參考:
ReactiveX/RxJava文檔中文版

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容