Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RxJava:merge()是否更改已发出项的顺序?_Java_Functional Programming_Rx Java_Reactive Programming_Rx Java2 - Fatal编程技术网

RxJava:merge()是否更改已发出项的顺序?

RxJava:merge()是否更改已发出项的顺序?,java,functional-programming,rx-java,reactive-programming,rx-java2,Java,Functional Programming,Rx Java,Reactive Programming,Rx Java2,请看以下两个小测试: @Test public void test1() { Observable.range(1, 10) .groupBy(v -> v % 2 == 0) .flatMap(group -> { if (group.getKey()) { return group; } return group; })

请看以下两个小测试:

@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合并了这些可见光的发射,以便它们可以交错

从文件:

“合并”可以交错由合并的可观察对象发出的项目(类似的运算符Concat不会交错项目,而是在开始从下一个可观察源发出项目之前,依次发出每个可观察源的所有项目)

引述如下:

在您的例子中,对于单个元素静态流,它不会产生任何真正的区别(但从理论上讲,merge可以以随机顺序输出单词,并且根据规范仍然有效)

如果您需要有保证的订单,请使用
concat*

第一个例子 它的工作原理如下:

  • 当发出
    1
    时,
    groupBy
    操作员将使用键
    false创建一个
    GroupedObservable
    • flatMap
      将从该可观察对象输出项目-当前仅为
      1
  • 当发出
    2
    时,
    groupBy
    操作员将使用键
    true
    创建一个
    GroupedObservable
    • flatMap
      现在还将输出第二个
      GroupedObservable
      -当前为
      2
  • 当发出
    3
    时,
    groupBy
    操作员将使用键
    false
    将其添加到现有的
    GroupedObservable
    中,
    flatMap
    将立即输出此项
  • 当发出
    4
    时,
    groupBy
    操作员将使用键
    true
    将其添加到现有的
    GroupedObservable
    中,
    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);
    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
1
key: true
2
3
...
key: false
key: true
map: 2
2
4
6
8
10
1
3
5
7
9
第二个例子 这是完全不同的,因为
toMap
将阻塞,直到上游完成:

  • 当发出
    1
    时,
    groupBy
    操作员将使用键
    false创建一个
    GroupedObservable
    • toMap
      将此
      GroupedObservable
      添加到内部映射,并使用键
      false
      (与
      GroupedObservable
      具有相同的键)
  • 当发出
    2
    时,
    groupBy
    操作员将使用键
    true
    创建一个
    GroupedObservable
    • toMap
      将此
      GroupedObservable
      添加到内部映射中,并使用键
      true
      (与
      GroupedObservable
      的键相同)-因此现在映射有2个
      GroupedObservable
  • 将以下数字添加到相应的
    GroupedObservables
    中,当源代码完成时,
    toMap
    操作符完成,并将映射传递给下一个操作符
  • flatMapObservable
    中,使用映射创建新的observable,首先添加偶数元素(key=
    true
    ),然后添加奇数元素(key=
    false
此外,您还可以在此处添加更多日志记录:

    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);
    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
1
key: true
2
3
...
key: false
key: true
map: 2
2
4
6
8
10
1
3
5
7
9

谢谢你的回答,但我还是不明白为什么
merge
内部
flatMapObservable
没有保留顺序。现在我知道
toMap
正在阻塞,因为它需要知道映射的键,以便在下一阶段发出它
在您的情况下,对于单元素静态流,它不会产生任何真正的区别
但是新映射中的2个可观察到的元素不是单元素,是吗?此外,我不确定在这种情况下,
static
是什么意思。
merge
的定义是元素可能会交错,这是我在本例中所期望的,相反,在flatMapObservable中,元素的行为就像一个
concat
在flatMapObservable中,您使用映射创建一个新的observable,首先添加偶数元素(key=true),然后添加奇数元素(key=false)
我想如果我做的是
concat
,这是正确的,但我做的是
合并
。对,你地图中的两个观测值各有5个元素-但它们是
静态的
(即不取决于某个时间)-换句话说:流已经完全定义,所有元素都已知
toMap
源流已经完成,映射中的可观察对象可以在订阅时立即输出其所有元素。ad第二条评论:在这种情况下,
merge
的行为与
concat
相同,这只是巧合。因此,这个
merge
实现显然订阅了第一个可观察对象(作为第一个参数传递的内容)并处理其所有数据,然后订阅第二个并处理第二个可观察对象的所有数据。但正如上面提到的:
merge
并不能保证这一点。好吧,巧合可能是个错误的词。但我想表达的是,
merge
,我们看到的行为依赖于实现。换句话说:其他Rx实现可能有不同的行为——甚至RxJava的更新版本也可能有不同的行为。