


flatMap() нужен, когда каждому элементу исходного потока соответствует несколько элементов результата. Например, из списка групп заданий нужно получить один список всех заданий. Обычный map() преобразует каждый элемент, но сам по себе не убирает дополнительный уровень вложенности.
Код для Java 17 создаёт три группы, включая пустую. Метод List::stream превращает каждую группу в поток, а flatMap() объединяет их содержимое.
import java.util.List;
public class FlattenTasks {
public static void main(String[] args) {
List<List<String>> groups = List.of(
List.of("read", "test"),
List.of(),
List.of("report")
);
List<String> tasks = groups.stream()
.flatMap(List::stream)
.toList();
System.out.println(tasks); // [read, test, report]
}
}
В этом последовательном потоке списков сохраняется порядок обхода: сначала задания первой группы, затем следующей. Пустая группа не добавляет элементов. Вызов toList() доступен начиная с Java 16 и возвращает список, который нельзя изменять через add(). Если нужен изменяемый результат, выбирайте способ сбора явно, например в ArrayList.
Выражение groups.stream().map(List::stream) имеет тип Stream<Stream<String>>. Его элементы сами являются потоками. После flatMap(List::stream) тип уже Stream<String>: дальше можно фильтровать отдельные задания или преобразовывать их названия.
Если задача состоит в подсчёте размеров каждой группы, вложенность убирать не требуется: map(List::size) даст поток чисел. Выбирайте операцию по нужной форме результата, а не по тому, какая выглядит сложнее. Один вызов flatMap снимает один уровень; он не обходит произвольное дерево рекурсивно.
В примере нет null: фабрика List.of() не принимает такие элементы. Если данные пришли из другого источника и содержат null вместо группы, вызов List::stream для неё завершится ошибкой. Сначала определите контракт: отсутствующая группа является ошибкой данных или означает пустую группу.
Фильтрация null допустима только во втором случае. Иначе она спрячет повреждённые данные. При этом документация flatMap отдельно допускает, что функция преобразования вернёт null вместо потока: он трактуется как пустой поток. Это не спасает ошибку, возникшую внутри самой функции при обращении к null.
distinct().Практику коллекций можно продолжить на курсе Java. Для разбора собственного преобразования данных на Mentoring.digital есть наставники по Java: полезно принести исходные типы, ожидаемый результат и спорные пустые значения.