Рубрики
Без рубрики

Разница между map() и flatMap()

Узнайте о различиях между map() и flatMap (), проанализировав некоторые примеры потоков и Необязательно.

Автор оригинала: baeldung.

1. Обзор

map() и flatMap() API происходят из функциональных языков. В Java 8 мы можем найти их в Optional , Stream и в CompletableFuture (хотя и под немного другим именем).

Потоки представляют собой последовательность объектов, в то время как необязательными являются классы, представляющие значение, которое может присутствовать или отсутствовать. Среди других агрегатных операций у нас есть методы map() и flatMap () .

Несмотря на то, что оба имеют одинаковые типы возврата, они совершенно разные. Давайте объясним эти различия, проанализировав некоторые примеры потоков и необязательных.

Дальнейшее чтение:

Итерация по карте в Java

Сериализация и десериализация карт с помощью Джексона

Как хранить дубликаты ключей на карте в Java?

2. Карта и плоская карта в необязательном

Метод map() хорошо работает с Необязательным — если функция возвращает точный тип, который нам нужен:

Optional s = Optional.of("test");
assertEquals(Optional.of("TEST"), s.map(String::toUpperCase));

Однако в более сложных случаях нам может быть предоставлена функция, которая также возвращает Необязательный . В таких случаях использование map() приведет к вложенной структуре, так как реализация map() выполняет дополнительную внутреннюю обертку.

Давайте рассмотрим другой пример, чтобы лучше понять эту ситуацию:

assertEquals(Optional.of(Optional.of("STRING")), 
  Optional
  .of("string")
  .map(s -> Optional.of("STRING")));

Как мы видим, в итоге мы получаем вложенную структуру Optional> . Хотя он работает, он довольно громоздок в использовании и не обеспечивает никакой дополнительной нулевой безопасности, поэтому лучше сохранить плоскую структуру.

Это именно то, что flatMap() помогает нам сделать:

assertEquals(Optional.of("STRING"), Optional
  .of("string")
  .flatMap(s -> Optional.of("STRING")));

3. Карта и плоская карта в потоках

Оба метода работают одинаково для Необязательно .

Метод map() обертывает базовую последовательность в экземпляр Stream , в то время как метод flatMap() позволяет избежать вложенной структуры Stream>|/.

Здесь map() создает Поток , состоящий из результатов применения метода toUpperCase() к элементам входного потока :

List myList = Stream.of("a", "b")
  .map(String::toUpperCase)
  .collect(Collectors.toList());
assertEquals(asList("A", "B"), myList);

map() работает довольно хорошо в таком простом случае. Но что, если у нас есть что-то более сложное, например, список списков в качестве входных данных?

Давайте посмотрим, как это работает:

List> list = Arrays.asList(
  Arrays.asList("a"),
  Arrays.asList("b"));
System.out.println(list);

Этот фрагмент выводит список списков [[a], [b]] .

Теперь давайте использовать flatMap() :

System.out.println(list
  .stream()
  .flatMap(Collection::stream)
  .collect(Collectors.toList()));

Результат такого фрагмента будет сглажен до [a, b] .

T he flatMap() метод сначала выравнивает входной поток из потоков в Поток из Строк (подробнее о выравнивании см. В этой статье ). После этого он работает аналогично методу map () .

4. Заключение

Java 8 дает нам возможность использовать методы map() и flatMap () , которые первоначально использовались в функциональных языках.

Мы можем вызывать их в потоках и необязательно. Эти методы помогают нам получить сопоставленные объекты, применяя предоставленную функцию сопоставления.

Как всегда, примеры в этой статье доступны на GitHub .