Разница между map () и flatMap ()
1. обзор
APImap() иflatMap() происходят от функциональных языков. В Java 8 вы можете найти их вOptional, Stream и вCompletableFuture (although под немного другим именем).
Streams представляют собой последовательность объектов, а необязательные параметры - это классы, представляющие значение, которое может присутствовать или отсутствовать. Среди других агрегатных операций у нас есть методыmap() иflatMap().
Несмотря на то, что оба имеют одинаковый тип возврата,, они сильно различаются. Давайте объясним эти различия, проанализировав несколько примеров потоков и опций.
Дальнейшее чтение:
Сериализация и десериализация карты с Джексоном
Краткое и практическое руководство по сериализации и десериализации Java Maps с использованием Jackson.
Как сохранить дубликаты ключей на карте в Java?
Краткое и практическое руководство по обработке дубликатов ключей с использованием мультикарт в Java.
2. Карта и плоская карта в опциях
Методmap() хорошо работает сOptional - если функция возвращает точный тип, который нам нужен:
Optional s = Optional.of("test");
assertEquals(Optional.of("TEST"), s.map(String::toUpperCase));
Однако в более сложных случаях нам может быть предоставлена функция, которая также возвращаетOptional. В таких случаях использованиеmap() приведет к вложенной структуре, поскольку реализацияmap() выполняет дополнительную внутреннюю оболочку.
Давайте посмотрим на другой пример, чтобы лучше понять эту ситуацию:
assertEquals(Optional.of(Optional.of("STRING")),
Optional
.of("string")
.map(s -> Optional.of("STRING")));
Как мы видим, мы получаем вложенную структуруOptional<Optional<String>>.. Хотя она и работает, она довольно громоздка в использовании и не обеспечивает никакой дополнительной нулевой безопасности, поэтому лучше сохранить плоскую структуру.
Именно в этом нам помогаетflatMap():
assertEquals(Optional.of("STRING"), Optional
.of("string")
.flatMap(s -> Optional.of("STRING")));
3. Карта и плоская карта в потоках
Оба метода работают одинаково дляOptional.
Методmap() оборачивает базовую последовательность в экземплярStream, тогда как методflatMap() позволяет избежать вложенной структурыStream<Stream<R>>.
В следующем примереmap() создаетStream, состоящий из результатов применения методаtoUpperCase() к элементам вводаStream:
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].
МетодTheflatMap() сначала выравнивает входнойStreamStreams доStreamStrings (подробнее о выравнивании см.article) с). После этого он работает аналогично методуmap().
4. Заключение
Java 8 дает нам возможность использовать методыmap() иflatMap(), которые изначально использовались в функциональных языках.
Мы можем вызывать их вStreams и Optionals. Эти методы помогают нам получить сопоставленные объекты, применяя предоставленную функцию сопоставления.
Как всегда, вы можете ознакомиться с примерами из этой статьиover on GitHub.