首页 > 解决方案 > 类似的 take()&groupBy() 代码应用于 timer() 导致不同的结果

问题描述

learnrxjava repo ( 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]

分别。我只是无法弄清楚为什么在第二种情况下结果会翻转。

谢谢。

标签: rx-java

解决方案


主要原因是take在 groupBy 完成之前偶数组的内部强制信号。

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

当源发出 18 时,真正的(偶数)组获取其所有 10 项并take发出一个onCompleted,完成列表,然后由 发出flatMap。接下来,源发出 19 完成假(奇)组并执行相同的操作。

当没有 innertake时,两个组都保持活动状态,直到源在 20 个项目后完成。完成后,首先groupBy通知假(奇)组完成,然后首先发出奇数列表,然后真(偶)组完成,发出偶数列表。


推荐阅读