看看这两个小测试:
@Test
public void test1() {
Observable.range(1, 10)
.groupBy(v -> v % 2 == 0)
.flatMap(group -> {
if (group.getKey()) {
return group;
}
return group;
})
.subscribe(System.out::println);
}
@Test
public void test2() {
Observable.range(1, 10)
.groupBy(v -> v % 2 == 0)
.toMap(g -> g.getKey())
.flatMapObservable(m -> Observable.merge(
m.get(true),
m.get(false)))
.subscribe(System.out::println);
}
我期望两个都以相同的顺序返回数字列表,所以:
1 2 3 4 5 6 7 8 9 10
但第二个示例返回
2 4 6 8 10 1 3 5 7 9
相反。
在第二个示例中,merge
似乎正在执行concat
,实际上,如果我将其更改为concat
,结果是相同的。
我想念什么?
谢谢。
答案 0 :(得分:2)
基本上flatMap
和merge
不保证所发射物品的顺序。
来自flatMap文档:
请注意,FlatMap将这些Observable的发射合并在一起,以便它们可以交织。
来自merge文档:
合并可能会交错合并合并的Observable发出的项目(类似的运算符Concat不会交错项目,但会依次开始发射每个源Observable的所有项目,然后才开始从下一个来源Observable发射项目。
此SO Answer的报价:
在您的情况下,对于单元素静态流,它没有任何实际的区别(但是从理论上讲,合并可能会以随机顺序输出单词,并且根据规范仍然有效)
如果您需要有保证的订单,请使用concat*
。
它是这样的:
1
时,groupBy
运算符将使用键GroupedObservable
创建一个false
flatMap
将输出此可观察项中的项目-当前仅1
2
时,groupBy
运算符将使用键GroupedObservable
创建一个true
flatMap
现在还将输出第二个GroupedObservable
中的项目-当前为2
3
时,groupBy
操作员将使用键GroupedObservable
将其添加到现有的false
中,flatMap
将立即输出该项目4
时,groupBy
操作员将使用键GroupedObservable
将其添加到现有的true
中,flatMap
将立即输出该项目它可以帮助您添加更多日志记录:
Observable.range(1, 10)
.groupBy(v -> v % 2 == 0)
.doOnNext(group -> System.out.println("key: " + group.getKey()))
.flatMap(group -> {
if (group.getKey()) {
return group;
}
return group;
})
.subscribe(System.out::println);
然后输出为:
key: false
1
key: true
2
3
...
这是完全不同的,因为toMap
将阻塞直到上游完成:
1
时,groupBy
运算符将使用键GroupedObservable
创建一个false
toMap
将此GroupedObservable
添加到内部映射并使用键false
(与GroupedObservable
拥有的键相同)2
时,groupBy
运算符将使用键GroupedObservable
创建一个true
toMap
会将此GroupedObservable
添加到内部地图中,并使用密钥true
(与GroupedObservable
拥有相同的密钥)-现在该地图有2个{ {1}} GroupedObservables
中,当源完成时,GroupedObservables
运算符完成,并将映射传递给下一个运算符toMap
中,您使用地图创建了一个新的可观察对象,您首先在其中添加了偶数元素(key = {flatMapObservable
),然后又添加了奇数元素(key = true
)还可以在此处添加更多日志记录:
false
然后输出为:
Observable.range(1, 10)
.groupBy(v -> v % 2 == 0)
.doOnNext(group -> System.out.println("key: " + group.getKey()))
.toMap(g -> g.getKey())
.doOnSuccess(map -> System.out.println("map: " + map.size()))
.flatMapObservable(m -> Observable.merge(
m.get(true),
m.get(false)
))
.subscribe(System.out::println);