看一下这两个小测试:
@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
,结果是相同的。我想念什么?
谢谢。
最佳答案
基本上flatMap
和merge
不保证所发射项目的顺序。
从flatMap doc:
请注意,FlatMap将这些Observable的发射合并在一起,以便它们可以交错。
从merge doc:
合并可能会交织合并的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个GroupedObservables
GroupedObservables
中,当源完成时,toMap
运算符完成,并将映射传递给下一个运算符flatMapObservable
中使用true
),然后添加奇数元素(key = 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);
然后输出是:
key: false
key: true
map: 2
2
4
6
8
10
1
3
5
7
9