RxJavaのフラットマップとスイッチマップの違い

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

RxJavaの紹介については、https://www.baeldung.com/rx-java[この記事]を参照してください。

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

  • flatMap 演算子は、供給された関数を使用してソースの観測可能値から返された各項目を独立した観測可能値に変換してから、すべての観測可能値を単一の観測可能値にマージします。オブザーバブルがマージされる順序は、ソースの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); assertThat(actualOutput, hasItems("b FirstResult", "b SecondResult", "boo FirstResult", "boo SecondResult", "bo FirstResult", "bo SecondResult", "book FirstResult", "book SecondResult", "books FirstResult", "books SecondResult"));

順番が毎回同じではないことに注意してください。

[[switchmap]]

===  ** **

**  __switchMap__演算子は、__flatMap__と似ていますが、直前の観測値のみを破棄した結果を保持します。

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

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

[source,java,gutter:,true]

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

ここで見るように、ソースの観測可能なものからの最新の入力項目を含む単一の観測可能なものだけを得ました。以前の結果はすべて破棄されました。

[[conclusion]]

===  ** **

要約すると、__switchMap__は__flatMap__とは異なり、提供された関数をソースObservableによって発行された最新のアイテムに適用した出力__flatMap__のみを保持し、順序を保証することなくすべての結果を保持して返します。

いつものように、この記事で使われているコードはhttps://github.com/eugenp/tutorials/tree/master/rxjava[GitHubで利用可能]です。