Зарегистрируйтесь, чтобы продолжить обучение

Декларативное программирование Java: Стримы

Декларативное программирование - это парадигма программирования, которая фокусируется на том, что компьютер должен сделать, а не том как это сделать. В этом уроке мы познакомимся с основами декларативного программирования и примерами его применения.

До сих пор мы, в основном, программировали в императивном стиле, в котором фокус идет на том как выполняется код. Классический пример это циклы, где мы указываем последовательность шагов, которые нужно выполнить, чтобы добиться нужного результата. Каждый шаг это ответ на вопрос как. Возьмем для примера сортировку пузырьком:

var fruits = new ArrayList<>(List.of("Orange", "Apple", "Banana", "Grapes", "Cherry"));

for (int i = 0; i < fruits.size(); i++) {
    for (int j = 0; j < fruits.size() - i - 1; j++) {
        if (fruits.get(j).compareTo(fruits.get(j + 1)) > 0) {
            // Обмен элементов
            var temp = fruits.get(j);
            fruits.set(j, fruits.get(j + 1));
            fruits.set(j + 1, temp);
        }
    }
}

System.out.println(fruits); // Вывод: [Apple, Banana, Cherry, Grapes, Orange]

Этот алгоритм мы можем описать как последовательность шагов:

  • Берем очередной элемент в списке, начиная с первого.
  • Начинаем очередной проход по списку
    • Если текущий элемент больше следующего, то
    • Создаем временную переменную, куда записываем текущий элемент.
    • Меняем текущий элемент на следующий.
    • Меняем следующий элемент на текущий через временную переменную.
    • Если прошлись по всему списку, то возвращаемся к началу

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

Именно такие задачи отлично решает декларативное программирование. Мы можем выделить процесс перебора и спрятать его таким образом, чтобы программисту осталось только показать как сравнивать два элемента между собой. Так мы получим декларативный код, который отвечает на вопрос "что мы хотим получить?", а вся логика сортировки, то есть того, как мы хотим этого получить, будет скрыта.

  var fruits = new ArrayList<>(List.of("Orange", "Apple", "Banana", "Grapes", "Cherry"));

  fruits.sort((v1, v2) -> v1.compareTo(v2));
  System.out.println(fruits); // Вывод: [Apple, Banana, Cherry, Grapes, Orange]

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

Стримы

Стримы представляют собой последовательность элементов с набором методов позволяющих преобразовывать эти элементы и выполнять над ними разнообразные вычисления. Исходная коллекция, в большинстве случаев, не меняется. Посмотрите на пример ниже. В течении курса вы научитесь не только понимать этот код, но и сможете написать его самостоятельно.

import java.util.List;
import java.util.stream.Collectors;

public class StreamExample {
    public static void main(String[] args) {
        // User(name, age)
        var users = List.of(
            new User("Alice", 22),
            new User("Bob", 17),
            new User("Charlie", 24),
            new User("Diana", 16)
        );

        var names = users.stream() // Создаем стрим
            .filter(user -> user.getAge() > 18) // Фильтрация пользователей старше 18 лет
            .map(User::getName) // Преобразование User в String (имя пользователя)
            .sorted() // Сортировка имен в алфавитном порядке
            .toList(); // Сбор результата в список

        names.forEach(System.out::println); // Вывод имен
    }
}

Основные элементы работы со стримами:

  • Коллекция сама по себе не является стримом, сначала нужно выполнить преобразование. В случае списков для этого нужно вызвать метод stream().
  • Почти всегда в конце работы стрима нужно преобразовать его в список toList(). Почему и зачем мы поговорим позже

Так как эти методы возвращают коллекцию, то мы можем объединять их в цепочки, создавая более сложные варианты обработки данных. Благодаря разделению и возможности комбинации, стримы позволяют решать большинство задач преобразования коллекций без необходимости возвращаться к циклам. Начиная со следующего урока мы рассмотрим подробно самые важные методы стримов.

Стримы работают и для массивов. Чтобы сделать стрим из массива, нужно вызвать метод Arrays.stream().

String[] chars = {"h", "e", "x", "l", "e", "t"};
var stream = Arrays.stream(chars);

Дальнейшая работа со стримом не зависит от того из чего он был получен. Об этом в следующих уроках.


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

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

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

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

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

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

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

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

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

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

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Программирование на Java, Разработка веб-приложений и микросервисов используя Spring Boot, проектирование REST API
10 месяцев
с нуля
Старт 26 декабря

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

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

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

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

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу