С каким функциональным интерфейсом взаимодействует метод flatMap в Java Stream API?

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

Ответ

Метод flatMap в Stream<T> ожидает аргумент типа Function<? super T, ? extends Stream<? extends R>>.

Разбор интерфейса:

  • T — тип элемента исходного потока.
  • R — тип элемента в результирующем потоке.
  • Функция принимает элемент T и возвращает новый поток (Stream<R>) элементов R.

Почему именно Function? Потому что операция является преобразованием (маппингом) каждого элемента, но с условием, что результат преобразования — это не один элемент, а множество (поток).

Пример: Разделение строк на символы

List<String> words = List.of("Hello", "World");
List<String> letters = words.stream()
    // Function<String, Stream<String>>: строка -> поток символов
    .flatMap(word -> word.chars()
                        .mapToObj(c -> String.valueOf((char) c)))
    .toList(); // Результат: [H, e, l, l, o, W, o, r, l, d]

Сравнение с map:

  • map(Function<T, R>): T -> R (один к одному).
  • flatMap(Function<T, Stream<R>>): T -> Stream<R> (один ко многим, с последующим слиянием).