Concat VS Merge运算符

时间:2016-08-11 17:54:50

标签: java java-8 rx-java

我正在检查RXJava的文档,我注意到concat和merge运算符似乎也是这样。 我写了几个测试以确定。

@Test
public void testContact() {

    Observable.concat(Observable.just("Hello"),
                      Observable.just("reactive"),
                      Observable.just("world"))
              .subscribe(System.out::println);
}

@Test
public void testMerge() {

    Observable.merge(Observable.just("Hello"),
                      Observable.just("reactive"),
                      Observable.just("world"))
            .subscribe(System.out::println);
}

文档说

  

Merge运算符也类似。它结合了两个或多个Observable的发射,但可以交错它们,而Concat从不交错多个Observable的发射。

但我仍然不完全理解,运行此测试数千次合并结果始终是相同的。由于订单未被授予,我有时会期待"被动" "世界" "你好"例如。

代码在这里https://github.com/politrons/reactive

3 个答案:

答案 0 :(得分:117)

如您所引用的文档中所述 - merge可以交错输出,而concat将首先等待更早的流完成,然后再处理后续流。 在你的情况下,对于单元素,静态流,它没有任何真正的区别(但理论上,合并可以按随机顺序输出单词,并且仍然根据规范有效)。如果你想看到差异,请尝试以下(之后你需要增加一些睡眠以避免提前退出)

    Observable.merge(
            Observable.interval(1, TimeUnit.SECONDS).map(id -> "A" + id),
            Observable.interval(1, TimeUnit.SECONDS).map(id -> "B" + id))
    .subscribe(System.out::println);
  

A0   B0   A1   B1   B2   A2   B3   A3   B4   A4

    Observable.concat(
            Observable.interval(1, TimeUnit.SECONDS).map(id -> "A" + id),
            Observable.interval(1, TimeUnit.SECONDS).map(id -> "B" + id))
    .subscribe(System.out::println);
  

A0   A1   A2   A3   A4   A5   A6   A7   A8

Concat将永远不会开始打印B,因为流A永远不会完成。

s / stream / observable / g;)

文档提供了很好的图表来显示差异。你需要记住,合并没有提供逐个交错项的保证,这只是一个可能的例子。

<强>的毗连

Concat operator合并

Merge operator

答案 1 :(得分:1)

如果两个来源都按照OP的说明进行同步,则它们分别通过 merge concat 返回准确的订单。

但是,当源不同步时,例如,两个源(如数据库)和套接字(例如,以随机或不确定的延迟推送数据)会导致 merge concat的结果或数据顺序不同

fun <T> Observable<T>.getAsyncItems(): Observable<T> {

    return concatMap {

        val delay = Random().nextInt(10)

        Observable.just(it)
                .delay(delay.toLong(), TimeUnit.MILLISECONDS)
    }
}

上面的扩展功能会给每个发射随机增加延迟,但是它们总是以相同的顺序发射。如果数据是A,B,C,D和E,则输出始终是A,B,C,D和E。

现在让我们比较一下mergeconcat在源异步时的行为。

val source1 =
        Observable.just("A", "B", "C", "D", "E").getAsyncItems()
val source2 =
        Observable.just(1, 2, 3, 4, 5).getAsyncItems()

Observable.merge(source1, source2).subscribe {print("$it-")}

打印类似A-B-1-C-2-D-3-4-E-5-A-1-2-3-B-C-D-4-E-5-的内容 这取决于随机延迟。

Observable.concat(source1, source2).subscribe {print("$it-")}

无论运行多少次,都打印A-B-C-D-E-1-2-3-4-5-

答案 2 :(得分:0)

Concat

Concat会从两个或多个Observable发出发射,而不会交织它们。发射物品时,它将保持可观察物的顺序。这意味着它将发出第一个可观察项的所有项,然后将发出第二个可观察项的所有项,依此类推。

Concat Operator

通过一个例子让我们清楚地理解它。

final String[] listFirst = {"A1", "A2", "A3", "A4"};
final String[] listSecond = {"B1", "B2", "B3"};

final Observable<String> observableFirst = Observable.fromArray(listFirst);
final Observable<String> observableSecond = Observable.fromArray(listSecond);

Observable.concat(observableFirst, observableSecond)
        .subscribe(new Observer<String>() {

            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String value) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

当我们使用Concat运算符时,它将保持顺序并发出值为A1,A2,A3,A4,B1,B2,B3。

合并

Merge通过合并它们的排放将多个Observable合并为一个。发出物品时它不会维持顺序。

Merge Operator

通过一个例子让我们清楚地理解它。

final String[] listFirst = {"A1", "A2", "A3", "A4"};
final String[] listSecond = {"B1", "B2", "B3"};

final Observable<String> observableFirst = Observable.fromArray(listFirst);
final Observable<String> observableSecond = Observable.fromArray(listSecond);

Observable.merge(observableFirst, observableSecond)
        .subscribe(new Observer<String>() {

            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String value) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });

由于我们正在使用合并运算符,因此它不会保持顺序,并且可以按任何顺序发出值,例如 A1,B1,A2,A3,B2,B3,A4 A1,A2,B1,B2,A3,A4,B3 ,也可以是任意值。

这是我们应该根据用例在RxJava中使用Concat和Merge运算符的方式。