RxJava 学习笔记(六) --- Transforming 变换操作符

时间:2022-07-19 17:50:05

1. Map —> 对序列的每一项都应用一个函数来变换Observable发射的数据序列

            RxJava 学习笔记(六) ---  Transforming 变换操作符

示例代码:

Observable.just(1,2,3,4,5,6).map(new Func1<Integer, Integer>() {
@Override
public Integer call(Integer integer) {
//对源Observable产生的结果,都统一乘以3处理
return integer*3;
}
}).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("next:" + integer);
}
});

输出

next:3 
next:6
next:9
next:12
next:15
next:18

2. Cast —> 操作符将原始Observable发射的每一项数据都强制转换为一个指定的类型,然后再发射数据,它是map的一个特殊版本。

            RxJava 学习笔记(六) ---  Transforming 变换操作符

cast操作符类似于map操作符,不同的地方在于map操作符可以通过自定义规则,把一个值A1变成另一个值A2A1A2的类型可以一样也可以不一样;而cast操作符主要是做类型转换的,传入参数为类型class,如果源Observable产生的结果不能转成指定的class,则会抛出ClassCastException运行时异常。

示例代码:

Observable.just(1,2,3,4,5,6).cast(Integer.class).subscribe(new Action1<Integer>() {
@Override
public void call(Integer value) {
System.out.println("next:"+value);
}
});

输出

next:1 
next:2
next:3
next:4
next:5
next:6

3. FlatMap —> 将Observable发射的数据集合变换为Observables集合,然后将这些Observable发射的数据平坦化的放进一个单独的Observable

FlatMap将一个发射数据的Observable变换为多个Observables,然后将它们发射的数据合并后放进一个单独的Observable
            RxJava 学习笔记(六) ---  Transforming 变换操作符

FlatMap操作符使用一个指定的函数对原始Observable发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的Observable,然后FlatMap合并这些Observables发射的数据,最后将合并后的结果当做它自己的数据序列发射。

这个方法是很有用的,例如,当你有一个这样的Observable:它发射一个数据序列,这些数据本身包含Observable成员或者可以变换为Observable,因此你可以创建一个新的Observable发射这些次级Observable发射的数据的完整集合。

Student[] students = ...;
Subscriber<Course> subscriber = new Subscriber<Course>() {
@Override
public void onNext(Course course) {
Log.d(tag, course.getName());
}
...
};
Observable.from(students)
.flatMap(new Func1<Student, Observable<Course>>() {
@Override
public Observable<Course> call(Student student) {
return Observable.from(student.getCourses());
}
})
.subscribe(subscriber);

注意:FlatMap对这些Observables发射的数据做的是合并(merge)操作,因此它们可能是交错的。

在许多语言特定的实现中,还有一个操作符不会让变换后的Observables发射的数据交错,它按照严格的顺序发射这些数据,这个操作符通常被叫作ConcatMap或者类似的名字。

注意:如果任何一个通过这个flatMap操作产生的单独的Observable调用onError异常终止了,这个Observable自身会立即调用onError并终止。

这个操作符有一个接受额外的int参数的一个变体。这个参数设置flatMap从原来的Observable映射Observables的最大同时订阅数。当达到这个限制时,它会等待其中一个终止然后再订阅另一个。

4. ConcatMap —> 它类似于最简单版本的flatMap,但是它按次序连接而不是合并那些生成的Observables,然后产生自己的数据序列。

concatMap()函数解决了flatMap()的交叉问题,提供了一种能够把发射的值连续在一起的铺平函数,而不是合并它们

            RxJava 学习笔记(六) ---  Transforming 变换操作符

看这篇文章flatMap()vs concatMap ,点我点我

5. SwitchMap —> 将Observable发射的数据集合变换为Observables集合,然后只发射这些Observables最近发射的数据

它和flatMap很像,除了一点:当原始Observable发射一个新的数据(Observable)时,它将取消订阅并停止监视产生执之前那个数据的Observable,只监视当前这一个。

RxJava 学习笔记(六) ---  Transforming 变换操作符

示例代码:

Observable.just("A", "B", "C", "D", "E").switchMap(new Func1<String, Observable<String>>() {
@Override
public Observable<String> call(String s) {
return Observable.just(s).subscribeOn(Schedulers.newThread());
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
System.out.println("------>onCompleted()");
}

@Override
public void onError(Throwable e) {
System.out.println("------>onError()" + e);
}

@Override
public void onNext(String s) {
System.out.println("------>onNext:" + s);
}
});
}

输出

------>onNext:E
------>onCompleted()

6. Scan —> 连续地对数据序列的每一项应用一个函数,然后连续发射结果

Scan操作符对原始Observable发射的第一项数据应用一个函数,然后将那个函数的结果作为自己的第一项数据发射。它将函数的结果同第二项数据一起填充给这个函数来产生它自己的第二项数据。它持续进行这个过程来产生剩余的数据序列。这个操作符在某些情况下被叫做accumulator

            RxJava 学习笔记(六) ---  Transforming 变换操作符

示例代码:

Observable.just(1, 2, 3, 4, 5)
.scan(new Func2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer sum, Integer item) {
return sum + item;
}
}).subscribe(new Subscriber<Integer>() {
@Override
public void onNext(Integer item) {
System.out.println("Next: " + item);
}

@Override
public void onError(Throwable error) {
System.err.println("Error: " + error.getMessage());
}

@Override
public void onCompleted() {
System.out.println("Sequence complete.");
}
});

输出:

Next: 1
Next: 3
Next: 6
Next: 10
Next: 15
Sequence complete.

有一个scan操作符的变体,你可以传递一个种子值给累加器函数的第一次调用(Observable发射的第一项数据)。如果你使用这个版本,scan将发射种子值作为自己的第一项数据。注意:传递null作为种子值与不传递是不同的,null种子值是合法的。

            RxJava 学习笔记(六) ---  Transforming 变换操作符

示例代码

Observable.just(1,2,3,4,5).scan(100, new Func2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer integer, Integer integer2) {
return integer + integer2;
}
}).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
System.out.println("Sequence complete.");
}

@Override
public void onError(Throwable e) {
System.err.println("Error: " + e.getMessage());
}

@Override
public void onNext(Integer integer) {
System.out.println("Next: " + integer);
}
});

输出

Next: 100
Next: 101
Next: 103
Next: 106
Next: 110
Next: 115

7. Buffer —> 它定期从Observable收集数据到一个集合,然后把这些数据集合打包发射,而不是一次发射一个

            RxJava 学习笔记(六) ---  Transforming 变换操作符

Buffer操作符将一个Observable变换为另一个,原来的Observable正常发射数据,变换产生的Observable发射这些数据的缓存集合。Buffer操作符在很多语言特定的实现中有很多种变体,它们在如何缓存这个问题上存在区别。

注意:如果原来的Observable发射了一个onError通知,Buffer会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始Observable发射的数据。

Window操作符与Buffer类似,但是它在发射之前把收集到的数据放进单独的Observable,而不是放进一个数据结构。

RxJava中有许多Buffer的变体:

buffer(count)

            RxJava 学习笔记(六) ---  Transforming 变换操作符

buffer(count)以列表(List)的形式发射非重叠的缓存,每一个缓存至多包含来自原始Observablecount项数据(最后发射的列表数据可能少于count项)

示例代码

Observable.range(1,5).buffer(2).subscribe(new Observer<List<Integer>>() {
@Override
public void onCompleted() {
System.out.println("-----------------onCompleted:");
}

@Override
public void onError(Throwable e) {
System.out.println("----------------->onError:");
}

@Override
public void onNext(List<Integer> strings) {
System.out.println("----------------->onNext:" + strings);
}
});

输出

----------------->onNext:[1, 2]
----------------->onNext:[3, 4]
----------------->onNext:[5]
-----------------onCompleted:

buffer(count, skip)

            RxJava 学习笔记(六) ---  Transforming 变换操作符

buffer(count, skip)从原始Observable的第一项数据开始创建新的缓存,此后每当收到skip项数据,用count项数据填充缓存:开头的一项和后续的count-1项,它以列表(List)的形式发射缓存,取决于countskip的值,这些缓存可能会有重叠部分(比如skip < count时),也可能会有间隙(比如skip > count时)。

示例代码: 取4个数 每次跳过2

Observable.range(1, 5).buffer(4, 2).subscribe(new Observer<List<Integer>>() {
@Override
public void onCompleted() {
System.out.println("-----------------onCompleted:");
}

@Override
public void onError(Throwable e) {
System.out.println("----------------->onError:");
}

@Override
public void onNext(List<Integer> strings) {
System.out.println("----------------->onNext:" + strings);
}
});

输出:

----------------->onNext:[1, 2, 3, 4]
----------------->onNext:[3, 4, 5]
----------------->onNext:[5]
-----------------onCompleted:

buffer(timespan, unit[, scheduler])

            RxJava 学习笔记(六) ---  Transforming 变换操作符

buffer(timespan, unit)定期以List的形式发射新的数据,每个时间段,收集来自原始Observable的数据(从前面一个数据包裹之后,或者如果是第一个数据包裹,从有观察者订阅原来的Observale之后开始)。还有另一个版本的buffer接受一个Scheduler参数,默认情况下会使用computation调度器。

示例代码:

    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {

if (subscriber.isUnsubscribed())
return;

try{

while (true){
subscriber.onNext("数据:"+df.format(new Date()));
SystemClock.sleep(2000);
}

}catch (Exception e){
subscriber.onError(e);
}

}
}).buffer(3,TimeUnit.SECONDS).subscribe(new Action1<List<String>>() {
@Override
public void call(List<String> strings) {
String s ="";
for (int i = 0 ; i < strings.size(); i++){

s = s+ ","+ strings.get(i);

}
System.out.println(s);
}
});

输出

,数据:2016-07-07 10:30:27,数据:2016-07-07 10:30:29
,数据:2016-07-07 10:30:31
,数据:2016-07-07 10:30:33,数据:2016-07-07 10:30:35
,数据:2016-07-07 10:30:37
,数据:2016-07-07 10:30:39,数据:2016-07-07 10:30:41
,数据:2016-07-07 10:30:43

8. Window —> 定期将来自原始Observable的数据分解为一个Observable窗口,发射这些窗口,而不是每次发射一项数据

WindowBuffer类似,但不是发射来自原始Observable的数据包,它发射的是Observables,这些Observables中的每一个都发射原始Observable数据的一个子集,最后发射一个onCompleted通知。

            RxJava 学习笔记(六) ---  Transforming 变换操作符

示例代码:

Observable.interval(1,TimeUnit.SECONDS).take(10).window(3,TimeUnit.SECONDS).subscribe(new Observer<Observable<Long>>() {  
@Override
public void onCompleted() {
LogUtils.d("------>onCompleted()");
}

@Override
public void onError(Throwable e) {
LogUtils.d("------>onError()" + e);
}

@Override
public void onNext(Observable<Long> integerObservable) {
LogUtils.d("------->onNext()");
integerObservable.subscribe(new Action1<Long>() {
@Override
public void call(Long integer) {
LogUtils.d("------>call():" + integer);
}
});
}
});

输出:

I/System.out: ------>call():0
I/System.out: ------>call():1
I/System.out: ------->onNext()
I/System.out: ------>call():2
I/System.out: ------>call():3
I/System.out: ------>call():4
I/System.out: ------->onNext()
I/System.out: ------>call():5
I/System.out: ------>call():6
I/System.out: ------>call():7
I/System.out: ------->onNext()
I/System.out: ------>call():8
I/System.out: ------>call():9
I/System.out: ------>onCompleted()

9. GroupBy —> 将Observable分拆为Observable集合,将原始Observable发射的数据按Key分组,每一个Observable发射一组不同的数据

            RxJava 学习笔记(六) ---  Transforming 变换操作符

GroupBy操作符将原始Observable分拆为一些Observables集合,它们中的每一个发射原始Observable数据序列的一个子序列。哪个数据项由哪一个Observable发射是由一个函数判定的,这个函数给每一项指定一个KeyKey相同的数据会被同一个Observable发射。

RxJava实现了groupBy操作符。它返回Observable的一个特殊子类GroupedObservable,实现了GroupedObservable接口的对象有一个额外的方法getKey,这个Key用于将数据分组到指定的Observable

有一个版本的groupBy允许你传递一个变换函数,这样它可以在发射结果GroupedObservable之前改变数据项。

注意:groupBy将原始Observable分解为一个发射多个GroupedObservableObservable,一旦有订阅,每个GroupedObservable就开始缓存数据。因此,如果你忽略这些GroupedObservable中的任何一个,这个缓存可能形成一个潜在的内存泄露。因此,如果你不想观察,也不要忽略GroupedObservable。你应该使用像take(0)这样会丢弃自己的缓存的操作符。

如果你取消订阅一个GroupedObservable,那个Observable将会终止。如果之后原始的Observable又发射了一个与这个ObservableKey匹配的数据,groupBy将会为这个Key创建一个新的GroupedObservable

groupBy默认不在任何特定的调度器上执行。

示例代码:

Observable.interval(1, TimeUnit.SECONDS).take(10).groupBy(new Func1<Long, Long>() {
@Override
public Long call(Long value) {
//按照key为0,1,2分为3组
return value % 3;
}
}).subscribe(new Action1<GroupedObservable<Long, Long>>() {
@Override
public void call(GroupedObservable<Long, Long> result) {
result.subscribe(new Action1<Long>() {
@Override
public void call(Long value) {
System.out.println("key:" + result.getKey() +", value:" + value);
}
});
}
});

输出:

key:0, value:0 
key:1, value:1
key:2, value:2
key:0, value:3
key:1, value:4
key:2, value:5
key:0, value:6
key:1, value:7
key:2, value:8
key:0, value:9