Как работает метод flatMap в Java Stream API?

«Как работает метод flatMap в Java Stream API?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Метод flatMap преобразует каждый элемент исходного потока (Stream) в новый поток, а затем объединяет ("склеивает") все полученные потоки в один результирующий. Это используется для работы с вложенными структурами данных.

Сигнатура:

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

Практический пример "разворачивания" списка списков:

import java.util.*;
import java.util.stream.*;

List<List<Integer>> nestedLists = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4, 5),
    Collections.emptyList(), // Пустая коллекция будет проигнорирована
    Arrays.asList(6)
);

List<Integer> flatList = nestedLists.stream() // Stream<List<Integer>>
    .flatMap(Collection::stream) // Преобразуем каждый List в Stream<Integer> и объединяем
    .collect(Collectors.toList());

System.out.println(flatList); // Вывод: [1, 2, 3, 4, 5, 6]

Ключевые особенности flatMap:

  • Функция-маппер должна возвращать Stream. Если она вернет null, будет выброшено NullPointerException.
  • Пустые потоки, полученные из маппера (например, от emptyList().stream()), не добавляют элементов в результат.
  • Порядок элементов в конечном потоке соответствует порядку обхода элементов исходного потока и вложенных коллекций.
  • Отличие от map: map преобразует 1 элемент в 1 элемент, flatMap — 1 элемент в 0, 1 или множество элементов.