Ответ
flatMap – это промежуточная операция Stream API, которая решает задачу "выравнивания" (flattening) структур данных. Она преобразует каждый элемент потока в новый поток (Stream), а затем объединяет (конкатенирует) все полученные потоки в один результирующий поток.
Простая аналогия: Если map преобразует [a, b, c] в [A, B, C], то flatMap может преобразовать [[1,2], [3,4]] в [1, 2, 3, 4].
Сигнатура:
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
Функция-маппер принимает элемент типа T и возвращает Stream<R>.
Ключевые примеры использования:
-
Преобразование списка списков в плоский список:
List<List<String>> listOfLists = Arrays.asList( Arrays.asList("a", "b"), Arrays.asList("c", "d") ); List<String> flatList = listOfLists.stream() .flatMap(List::stream) // Преобразуем каждый List в Stream<String> .collect(Collectors.toList()); // Результат: [a, b, c, d] -
Разделение строк на слова:
List<String> sentences = Arrays.asList("Hello world", "Java Streams"); List<String> words = sentences.stream() .flatMap(sentence -> Arrays.stream(sentence.split(" "))) // String -> Stream<String> .collect(Collectors.toList()); // [Hello, world, Java, Streams] -
Обработка Optional (Java 9+):
List<Optional<String>> optionals = Arrays.asList(Optional.of("A"), Optional.empty(), Optional.of("B")); List<String> values = optionals.stream() .flatMap(Optional::stream) // Optional.stream() возвращает пустой или одноэлементный поток .collect(Collectors.toList()); // [A, B]
Отличие от map:
map(Function<T, R>): 1 элемент -> 1 элемент. Результат:Stream<R>.flatMap(Function<T, Stream<R>>): 1 элемент -> N элементов (поток). Результат:Stream<R>(уже "выровненный").
Итог: flatMap – это мощный инструмент для работы с вложенными или составными элементами, когда нужно получить единый поток из множества источников.