Concat VS Оператор слияния

Я проверял документацию 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 также схож. Он объединяет выбросы двух или более наблюдаемых, но может чередовать их, тогда как Concat никогда не смешивает выбросы от нескольких Observables.

Но все-таки я не понимаю, запустив этот тест тысячу раз, результат слияния всегда один и тот же. Поскольку заказ не предоставляется, я ожидал иногда "реактивный" "мир", например, "привет".

Код находится здесь https://github.com/politrons/reactive

Ответ 1

Это описано в документации, которую вы указали. Объединение может чередовать выходы, в то время как 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/поток/наблюдаемый /g;)

Документация дает хорошие графики, чтобы показать разницу. Вы должны помнить, что слияние не дает никаких гарантий чередования элементов один за другим, это всего лишь один из возможных примеров.

Concat

Concat operator Слияние

Merge operator

Ответ 2

Concat

Concat испускает выбросы от двух или более Observables, не чередуя их. Это будет поддерживать порядок наблюдаемых во время испускания предметов. Это означает, что он будет излучать все элементы первой наблюдаемой, а затем будет излучать все элементы второй наблюдаемой и так далее.

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 Operator, он будет поддерживать порядок и выдавать значения как A1, A2, A3, A4, B1, B2, B3.

сливаться

Слияние объединяет несколько наблюдаемых в одну, объединяя их выбросы. Он не будет поддерживать порядок при выделении предметов.

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. или может быть что угодно.

Вот как мы должны использовать операторы Concat и Merge в RxJava в зависимости от нашего варианта использования.