将类似take()&groupBy()的代码应用于timer()导致不同的结果

时间:2019-06-04 22:23:58

标签: rx-java

learnerxjava存储库(https://github.com/jhusain/learnrxjava)中的以下两段代码会产生不同的结果:

Observable.timer(0, 1, TimeUnit.MILLISECONDS)
                .groupBy(n -> n % 2 == 0)
                .flatMap(g -> {
                    return g.take(10).toList();
                }).take(2).toBlocking().forEach(System.out::println);

Observable.timer(0, 1, TimeUnit.MILLISECONDS)
                .take(20)
                .groupBy(n -> n % 2 == 0)
                .flatMap(g -> {
                    return g.toList();
                })
                .toBlocking()
                .forEach(System.out::println);

收益

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

分别。我只是不知道为什么在第二种情况下结果会被翻转。

谢谢。

1 个答案:

答案 0 :(得分:0)

主要原因是内部take在groupBy完成之前迫使偶数组发信号。

GroupBy在地图中拥有两个组,对于 false(奇数组) true(偶数组) ,它们具有自然顺序。

当源发出18个信号时, true(偶数)组获得其所有10项,并且take发出onCompleted,完成列表,然后由{ {1}}。接下来,源发出19,它完成 false(奇数)组并执行相同的操作。

如果没有内部flatMap,则两个组都将保持活动状态,直到源完成20个项目为止。完成后,take首先通知 false(奇数)组有关完成情况,然后首先发出奇数列表,然后 true(偶数)组为完成,发出偶数列表。