RxJavaでの観測量の組み合わせ

RxJavaでオブザーバブルを結合する

1. 前書き

このクイックチュートリアルでは、RxJavaでObservablesを組み合わせるさまざまな方法について説明します。

RxJavaを初めて使用する場合は、まずこのintro tutorialを確認してください。

それでは、すぐに始めましょう。

2. Observables

Observableシーケンス、または単にObservablesは、非同期データストリームの表現です。

これらはObserver patternに基づいており、Observerと呼ばれるオブジェクトがObservableによって発行されたアイテムをサブスクライブします。

Observerは、Observableが将来放出するものに反応するため、サブスクリプションは非ブロッキングです。 これにより、並行性が促進されます。

RxJavaでの簡単なデモンストレーションは次のとおりです。

Observable
  .from(new String[] { "John", "Doe" })
  .subscribe(name -> System.out.println("Hello " + name))

3. オブザーバブルの組み合わせ

リアクティブフレームワークを使用してプログラミングする場合、さまざまなObservablesを組み合わせるのが一般的なユースケースです。

たとえば、Webアプリケーションでは、互いに独立した2セットの非同期データストリームを取得する必要がある場合があります。

次のストリームを要求する前に前のストリームが完了するのを待つ代わりに、両方を同時に呼び出して、結合されたストリームをサブスクライブすることができます。

このセクションでは、RxJavaで複数のObservablesを組み合わせることができるいくつかのさまざまな方法と、各方法が適用されるさまざまなユースケースについて説明します。

3.1. Merge

merge演算子を使用して、複数のObservablesの出力を組み合わせて、1つのように機能させることができます。

@Test
public void givenTwoObservables_whenMerged_shouldEmitCombinedResults() {
    TestSubscriber testSubscriber = new TestSubscriber<>();

    Observable.merge(
      Observable.from(new String[] {"Hello", "World"}),
      Observable.from(new String[] {"I love", "RxJava"})
    ).subscribe(testSubscriber);

    testSubscriber.assertValues("Hello", "World", "I love", "RxJava");
}

3.2. MergeDelayError

mergeDelayErrorメソッドは、複数のObservablesを1つに結合するという点で、mergeと同じですが、if errors occur during the merge, it allows error-free items to continue before propagating the errorsは次のようになります。

@Test
public void givenMutipleObservablesOneThrows_whenMerged_thenCombineBeforePropagatingError() {
    TestSubscriber testSubscriber = new TestSubscriber<>();

    Observable.mergeDelayError(
      Observable.from(new String[] { "hello", "world" }),
      Observable.error(new RuntimeException("Some exception")),
      Observable.from(new String[] { "rxjava" })
    ).subscribe(testSubscriber);

    testSubscriber.assertValues("hello", "world", "rxjava");
    testSubscriber.assertError(RuntimeException.class);
}

上記の例emits all the error-free values

hello
world
rxjava

mergeDelayErrorの代わりにmergeを使用する場合、mergeObservablesエラー発生時。

3.3. Zip

zip拡張メソッドbrings together two sequences of values as pairs

@Test
public void givenTwoObservables_whenZipped_thenReturnCombinedResults() {
    List zippedStrings = new ArrayList<>();

    Observable.zip(
      Observable.from(new String[] { "Simple", "Moderate", "Complex" }),
      Observable.from(new String[] { "Solutions", "Success", "Hierarchy"}),
      (str1, str2) -> str1 + " " + str2).subscribe(zippedStrings::add);

    assertThat(zippedStrings).isNotEmpty();
    assertThat(zippedStrings.size()).isEqualTo(3);
    assertThat(zippedStrings).contains("Simple Solutions", "Moderate Success", "Complex Hierarchy");
}

3.4. 間隔を置いて圧縮する

この例では、intervalを使用してストリームを圧縮します。これにより、実際には最初のストリームの要素の放出が遅延します。

@Test
public void givenAStream_whenZippedWithInterval_shouldDelayStreamEmmission() {
    TestSubscriber testSubscriber = new TestSubscriber<>();

    Observable data = Observable.just("one", "two", "three", "four", "five");
    Observable interval = Observable.interval(1L, TimeUnit.SECONDS);

    Observable
      .zip(data, interval, (strData, tick) -> String.format("[%d]=%s", tick, strData))
      .toBlocking().subscribe(testSubscriber);

    testSubscriber.assertCompleted();
    testSubscriber.assertValueCount(5);
    testSubscriber.assertValues("[0]=one", "[1]=two", "[2]=three", "[3]=four", "[4]=five");
}

4. 概要

この記事では、ObservablesをRxJavaと組み合わせる方法をいくつか見てきました。 official RxJava documentationで、combineLatestjoingroupJoinswitchOnNextなどの他のメソッドについて学ぶことができます。

いつものように、この記事のソースコードはGitHub repoで入手できます。