Шаг 115.
Язык программирования Java.
Stream Api

На этом шаге мы начнем знакомиться со Stream Api

Stream - это последовательность элементов (возможно бесконечная) с поддержкой различных преобразований. Рассмотрим следующий пример:

List<User> users = getAllUsers();

System.out.println("Все пользователи");
users.forEach(System.out::println);

System.out.println("\nСписок пользователей (первые 3), возраст которых больше 10");
users.stream()
        .filter(u -> u.getAge() > 10)
        .sorted(Comparator.comparing(User::getName))
        .limit(3)
        .forEach(System.out::println);

В данном фрагменте программы с помощью функции getAllUsers получаем список пользователей (список объектов типа User). В объекте типа User хранится информация о имени пользователя и его возраст. Получить имя пользователя можно с помощью функции getName, а возраст с помощью функции getAge. С помощью данного фрагмента программы мы получаем три первых (в алфавитном порядке) пользователя, у которых возраст больше 10.

При работе со Stream Api задаются 3 компонента:

  1. Источник.
  2. Промежуточные операции (могут отсутствовать).
  3. Терминальная операция.

Источником в данном примере является список users. Промежуточные операции данном примере - это функции filter, sorted и limit. Есть одна особенность промежуточных функций - они “ленивые”. Данные функции на самом деле не выполняют ничего с источником. Они лишь задают “рецепт” конструирования новой последовательности элементов. Заметим, что каждая промежуточная функция возвращает объект типа Stream. Это позволяет строить целые цепочки вызовов таких функций, как это показано в примере выше. Все действия с “рецептами” происходят в терминальной функции. Данная функция всегда является последней функцией в цепочке вызовов. Такая функция уже возвращает объект, отличный от Stream (возможно даже void). В нашем случае это функция forEach, с помощью которой мы проходим по полученному списку и выводим его на экран.

Для того, чтобы убедиться что промежуточные функции не выполняются, пока не будет вызвана терминальная функция, наберите следующий пример:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

System.out.println("Вывод начался");
list.stream().filter(value -> {
    System.out.println(value);
    return value % 2 == 0;
});
System.out.println("Вывод закончился");
/* Output:
Вывод начался
Вывод закончился
*/

На следующем шаге мы поговорим про источников типа Stream

Предыдущий шаг Содержание Следующий шаг