1. 概要

RxJavaは、オブザーバブルによって発行されたアイテムを他のオブザーバブルに変換するためのさまざまな演算子を提供します。 最も人気のある演算子の2つは、flatMapswitchMapです。 2つの違いは、リアクティブプログラミングの初心者にとっては理解しにくいことがよくあります。

RxJavaの概要については、この記事を参照してください。

このチュートリアルでは、簡単な例を見て、違いを理解します。

2. flatMap

flatMapオペレーターは、提供された関数を使用して、ソースobservableから返された各アイテムを独立したobservableに変換し、すべてのobservableを単一のobservableにマージします。 オブザーバブルがマージされる順序は、ソースオブザーバブルと同じであるとは限りません。

例として検索エンジンを取り上げましょう。 単語の各文字を入力した直後に検索結果を表示したいとします。

わかりやすくするために、検索クエリの入力を単語のリストとして使用しました。

また、単語ごとに常に2つの検索結果が返されます。

// given
List<String> actualOutput = new ArrayList<>();
TestScheduler scheduler = new TestScheduler();
List<String> keywordToSearch = Arrays.asList("b", "bo", "boo", "book", "books");

// when
Observable.fromIterable(keywordToSearch)
  .flatMap(s -> Observable.just(s + " FirstResult", s + " SecondResult")
    .delay(10, TimeUnit.SECONDS, scheduler))
  .toList()
  .doOnSuccess(s -> actualOutput.addAll(s))
  .subscribe();

scheduler.advanceTimeBy(1, TimeUnit.MINUTES);

// then
assertThat(actualOutput, hasItems("b FirstResult", "b SecondResult",
  "boo FirstResult", "boo SecondResult",
  "bo FirstResult", "bo SecondResult",
  "book FirstResult", "book SecondResult",
  "books FirstResult", "books SecondResult"));

順序はすべての実行で常に同じであるとは限らないことに注意してください。

3. switchMap

switchMap 演算子は、 flatMap に似ていますが、最新の監視可能な結果のみを保持し、前の結果を破棄する点が異なります。

部分的なクエリ文字列ではなく、最後の完全に形成された単語(この場合は「本」)の検索結果のみを取得するという要件を変更しましょう。 これを実現するために、switchMapを使用できます。

上記のコード例でflatMapswitchMapに置き換えるだけの場合、次のアサーションが有効になります。

assertEquals(2, actualOutput.size());
assertThat(actualOutput, hasItems("books FirstResult", "books SecondResult"));

ここに表示されているように、ソースobservableからの最新の入力アイテムを含む1つのobservableのみを取得しました。 以前の結果はすべて破棄されました。

4. 結論

要約すると、switchMapflatMapとは異なり、提供された関数をソースObservable flatMapによって発行された最新のアイテムに適用する出力のみを保持します。一方、すべての結果を保持し、順序を保証せずにインターリーブされた方法でそれらを返します。

いつものように、この記事で使用されているコードは、GitHubから入手できます。