转换类操作符顾名思义,就是将上游(被观察者)发送的数据进行转换成另一种形式(观察者希望接收的形式),从而使下游(观察者)能个正确的接受并作出响应;
这里介绍 map,flatMap,flatMapIterable,concatMap,switchMap,scan,cast,buffer,window,groupBy 进行讲解。
Student类
data class Student(var name: String,var score:Int)
1. map
对Observable发射的每一项数据应用一个函数,执行变换操作;
map操作符对原始Observable发射的每一项数据应用一个你选择的函数,然后返回一个发射这些结构的Observable
第一次转换,将字符串 “HELLO“ 转换成全是小写字母的字符串 ”hello“。第二次转换,在字符串 ”hello“ 后面添加新的字符串 ” world!“,它们组成了新的字符串也就是执行结果。所以map的作用就是将接收类型为T的Observable 转换成接收类型为R的Observable。
Observable.just("HELLO")
.map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return s.toLowerCase(); //转为小写
}
})
.map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return s + " world!"; //加 world
}
})
.subscribe(new Consumer<String>() { //订阅输出
@Override
public void accept(String s) throws Exception {
System.out.println("Next: " + s);
}
});
//运行结果
Next: hello world!
2. cast
cast运算符作用和map类似,但是它只能将父类对象转换为子类对象,是map的特殊版本。
方法声明:Observable<R> cast(final Class<R> klass),将源事件类型转换成klass的数据类型。
-
注意只能将父类对象转为子类对象;
-
cast执行转化必须是可以转的,如果该父类对象无法转为子类对象,会抛出classCastException异常;
List<Person> personList = new ArrayList<>(studentList);
Observable.from(personList)
.cast(Student.class)
.subscribe(student -> System.out.println(student.getId()));
3. flatMap
flatMap 将一个发射数据的Observable转变为多个Observables,然后将它们的数据合并后放入一个单独的Observable
flatMap 操作符使用一个指定的函数对原始Observable发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据Observable,然后flatMap 合并这些Observable发射的数据,最后将合并后的结构当做它自己的数据序列发射。
flatMap 对这些 Observables 发射的数据做的是合并 (merge) 操作, 因此它们可能是交错的。还有一个操作符不会让变换后 Observables 发射的数据交错,它严格按照顺序发射这些数据,这个操作符就是 concatMap
下面看一个例子,先定义一个用户对象,包含用户名 和 地址由于地址可能包括生活、工作等地方,所以使用一个List对象来表示.
private class User {
public String username;
public List<Address> addresses;
public static class Address {
public String street;
public String city;
}
}
//使用 flatMap
public static void tesFlattMap() {
List<User.Address> addresses = new ArrayList<>();
addresses.add(new User.Address("北京"));
addresses.add(new User.Address("上海"));
addresses.add(new User.Address("宣化"));
User user = new User();
user.addresses = addresses;
//如果想要打印出某个用户所有的地址,那么可以借助map操作符返回一个地址的列表。
Observable.just(user)
.map(new Function<User, List<User.Address>>() {
@Override
public List<User.Address> apply(@NonNull User user) throws Exception {
return user.addresses;
}
})
.subscribe(new Consumer<List<User.Address>>() {
@Override
public void accept(List<User.Address> addresses) throws Exception {
for (User.Address address : addresses) {
System.out.println(address.city);
}
}
});
//使用flatMap操作符后, flatMap内部将用户地址列表转换成一个Observable
Observable.just(user)
.flatMap(new Function<User, ObservableSource<User.Address>>() {
@Override
public ObservableSource<User.Address> apply(@NonNull User user) throws Exception {
return Observable.fromIterable(user.addresses);
}
})
.subscribe(new Consumer<User.Address>() {
@Override
public void accept(User.Address address) throws Exception {
System.out.println(address.city);
}
});
}
//执行结果
北京
上海
4. flatMapIterable
flatMapIterable跟flatMap相差无几,区别在于flatMapIterable转换后的是一个Iterable对象,最后将所有的Iterable都传入一个Observable中,由这个Observable来将事件发送出去。
Observable.just(user)
.flatMapIterable(new Function<User, Iterable<User.Address>>() {
@Override
public Iterable<User.Address> apply(@NonNull User user) throws Exception {
return user.addresses;
}
}).subscribe(new Consumer<User.Address>() {
@Override
public void accept(User.Address address) throws Exception {
System.out.println(address.city);
}
});
5. concatMap
concatMap操作符的功能和flatMap是非常相似的,只是有一点,concatMap 最终输出的数据序列和原数据序列是一致,
它是按顺序链接Observables,而不是合并(flatMap用的是合并)。
Observable.just(user)
.concatMap(new Function<User, ObservableSource<User.Address>>() {
@Override
public ObservableSource<User.Address> apply(@NonNull User user) throws Exception {
return Observable.fromIterable(user.addresses);
}
}).subscribe(new Consumer<User.Address>() {
@Override
public void accept(User.Address address) throws Exception {
System.out.println(address.city);
}
});
6. switchMap
switchMap(Func1) 和 flatMap(Func1) 很像, 区分是,每当Observable发射一个新的数据项Observable时,它将取消订阅并停止监听之前那个数据项产生的Observable,并开始监视当前发射的这一个。
7. scan
san(Fun2)将前一个事件产生的结果发送到下一个事件转换时的第一个参数使用;
Observable<T> scan(Func2<T, T, T> accumulator)
Observable<R> scan(R initialValue, Func2<R, ? super T, R> accumulator)
Observable.just(1, 2, 3, 4, 5)
.scan(new BiFunction<Integer, Integer, Integer>() {
@NonNull
@Override
public Integer apply(@NonNull Integer integer, @NonNull Integer integer2) throws Exception {
//把每次执行结果给第一个参数 Integer
return integer + integer2;
}
})
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
//执行结果
1
3
6
10
15
8. buffer
buffer就是将原有的事件转换成一个List列表,由一个新的Observable一次性发送出去,方法声明如下:
Observable<List<T>> buffer(int count)
Observable<List<T>> buffer(int count, int skip)
buffer 操作符将 Observable 变换为另一个,原来的Observable正常发射数据,由产生 Observable 发射这些数据的缓存集合。
buffer(count)
Observable.range(1, 10)
.buffer(2) // 2个一组
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers) throws Exception {
System.out.println("Next->" + integers);
}
});
//执行结果
Next->[1, 2]
Next->[3, 4]
Next->[5, 6]
Next->[7, 8]
Next->[9, 10]
buffer(count,skip)
Observable.range(1, 10)
.buffer(2,3)
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers) throws Exception {
System.out.println("Next->" + integers);
}
});
//执行结果
Next->[1, 2]
Next->[4, 5]
Next->[7, 8]
Next->[10]
9. window
window与buffer的作用非常相似,区别在于buffer发送出去的是一个列表List,而window发送出去的事件是一个Observable对象
Observable<Observable<T>> window(int count)
Observable<Observable<T>> window(int count, int skip)
Observable.range(1, 10)
.window(2,3)
.subscribe(new Consumer<Observable<Integer>>() {
@Override
public void accept(Observable<Integer> integerObservable) throws Exception {
integerObservable.subscribe(integer -> System.out.println("Next->" + integer));
}
});
//执行结果
Next->1
Next->2
Next->4
Next->5
Next->7
Next->8
Next->10
10. groupBy
将一个Observable分拆为一些Observables集合,它们中的每一个发射原始Observable的一个子序列。
GroupBy操作符将原始Observable分拆为一些Observables集合,它们中的每一个发射原始Observable数据序列的一个子序列。
哪个数据项由哪个Observable发射是由函数判定的,该函数给每一项指定一个Key,Key相同的数据会被同一个Observable发射。
List<Student> students = new ArrayList<>();
students.add(new Student("U1111", 59));
students.add(new Student("U1112", 69));
students.add(new Student("U1113", 37));
students.add(new Student("U1114", 72));
students.add(new Student("U1115", 26));
students.add(new Student("U1116", 98));
students.add(new Student("U1117", 53));
students.add(new Student("U1118", 60));
students.add(new Student("U1119", 100));
Observable.fromIterable(students)
.groupBy(new Function<Student, Integer>() {
@Override
public Integer apply(@NonNull Student student) throws Exception {
return student.getScore() >= 60 ? 1 : 0;
}
})
.subscribe(new Consumer<GroupedObservable<Integer, Student>>() {
@Override
public void accept(GroupedObservable<Integer, Student> integerStudentGroupedObservable) throws Exception {
integerStudentGroupedObservable.subscribe(student -> {
if (integerStudentGroupedObservable.getKey() == 0) {
System.out.println("不及格ID: " + student.getName() +" ,score: "+ student.getScore());
} else {
System.out.println("及格ID: " + student.getName() +" ,score: "+ student.getScore());
}
});
}
});
//执行结果
不及格ID: U1111 ,score: 59
及格ID: U1112 ,score: 69
不及格ID: U1113 ,score: 37
及格ID: U1114 ,score: 72
不及格ID: U1115 ,score: 26
及格ID: U1116 ,score: 98
不及格ID: U1117 ,score: 53
及格ID: U1118 ,score: 60
及格ID: U1119 ,score: 100