Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Выравнивание данных (Flat Map) Java: Стримы

В разработке иногда встречается задача "выпрямления" вложенных списков, то есть создания одного плоского списка из списка списков или списка массивов. В стримах за это отвечает метод flatMap(), который работает как показано в коде ниже.

var listOfLists = List.of(
    List.of(1, 2, 3),
    List.of(4, 5, 6),
    List.of(7, 8, 9)
);

// Stream<List<Integer>> to Stream<Integer>
var flattenedList = listOfLists.stream()
    .flatMap(List::stream)
    .toList();

System.out.println(flattenedList); // Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

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

Особенно часто flatMap() встречается в работе с файловой системой при чтении списка файлов и директорий, а так же при работе с содержимым файлов. Ниже мы разберем подобный пример, но если он вам покажется слишком сложным, то не переживайте, просто пропустите его и вернитесь позже.

Для примера посчитаем частоту слов в файле. Для этого прочитаем файл с помощью File.lines(), этот метод возвращает стрим состоящий из строк файла. Именно здесь нам понадобится flatMap() для обработки каждой строки.

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.stream.Collectors;

try (var lines = Files.lines(Path.of("README.md"))) {
    var res = lines.flatMap(line -> Arrays.stream(line.trim().split("\\s+")))
                   .map(String::toLowerCase)
                   .collect(Collectors.groupingBy(word -> word, Collectors.counting()));
    System.out.println(res);
}

Это маленькая программа, но в ней происходит очень много всего сразу. Разберем ее построчно.

  • Конструкция try нужна для работы с такими ресурсами как файлы, она никак не влияет на нашу программу, поэтому не обращаем на нее внимание, она изучается позже.
  • Читается файл README.md построчно в переменную lines. Метод Files.lines возвращает Stream<String>.
  • Вызывается flatMap(), который преобразует набор строк в плоский список слов. Для этого внутри лямбды каждая строка разбивается на слова. Получившийся массив преобразуется в стрим с помощью Arrays.stream.
  • Все слова приводятся к нижнему регистру, на случай если они были написаны по-разному. Это называется нормализацией данных.
  • Выполняется группировка слов по частоте.

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 25 000 ₸ в месяц
Разработка приложений на языке Java
10 месяцев
с нуля
Старт 21 ноября

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»