1. Обзор
RxJava предоставляет различные операторы для преобразования элементов, испускаемых наблюдаемым объектом, в другие наблюдаемые объекты. Двумя наиболее популярными операторами являются flatMap
и switchMap
. Разницу между ними часто трудно понять новичкам в реактивном программировании.
Для ознакомления с RxJava обратитесь к этой статье .
В этом уроке мы поймем разницу, рассмотрев простой пример.
2. плоская карта
Оператор flatMap
преобразует каждый элемент, возвращенный из исходного наблюдаемого объекта, в независимый наблюдаемый объект с помощью предоставленной функции, а затем объединяет все наблюдаемые объекты в один наблюдаемый объект . Порядок, в котором объединяются наблюдаемые, не обязательно будет таким же, как в исходном наблюдаемом.
Возьмем в качестве примера поисковую систему. Учтите, что мы хотим отображать результаты поиска сразу после ввода каждого символа слова:
Для простоты мы взяли ввод поискового запроса в виде списка слов.
Кроме того, мы всегда возвращаем два результата поиска для каждого слова.
// 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
похож на flatMap
, за исключением того, что он сохраняет результат только последнего наблюдаемого объекта, отбрасывая предыдущие.
Давайте изменим наше требование: мы хотим получать результаты поиска только для конечного полностью сформированного слова (в данном случае «книги»), а не для частичных строк запроса. Для этого мы можем использовать switchMap
.
Если мы просто заменим flatMap
на switchMap
в приведенном выше примере кода, следующие утверждения будут действительными:
assertEquals(2, actualOutput.size());
assertThat(actualOutput, hasItems("books FirstResult", "books SecondResult"));
Как мы видим здесь, мы получили только одну наблюдаемую, содержащую последний входной элемент из исходной наблюдаемой. Все предыдущие результаты были отброшены.
4. Вывод
Подводя итог, switchMap
отличается от flatMap
тем, что он сохраняет только вывод применения предоставленной функции к последнему элементу, испускаемому исходным Observable, а flatMap
, с другой стороны, сохраняет все результаты и возвращает их в чередующемся порядке, не гарантируя порядок.
Как всегда, код, использованный в этой статье, доступен на GitHub .