Статьи
YouTube-канал

Промежуточные операции Stream API

7 апреля 2019

Тэги: Collections Java 8 Stream API

Содержание

  1. Преобразование
  2. Фильтрация
  3. Доступ к элементу
  4. Удаление дублей
  5. Сортировка
  6. Ограничение по количеству элементов
  7. Пропуск первых элементов
  8. Разворачивание многомерных структур
  9. Выводы

Все методы Stream API можно разделить на две группы: промежуточные и терминальные (конечные). Промежуточные операции следует воспринимать как «отложенные», т.е. они не меняют сами данные, а только задают правила их изменения. А терминальные как раз инициируют всю цепочку преобразований и возвращают модифицированные данные.

Рассмотрим промежуточные операции. Все промежуточные операции возвращают типизированный интерфейс Stream<>.

Преобразование

Любое изменение исходного элемента можно делать с помощью метода map(). В качестве параметра метод принимает лямбда-выражение.

Stream.of(1, 2, 3, 4, 5, 6)
        .map(n -> n * 10) // умножает каждый элемент на 10
Stream.of("apple", "orange")
        .map(String::toUpperCase) // преобразует буквы в каждом слове в верхний регистр

Во втором случае мы воспользовались краткой записью лямбда-выражения через method reference.

Фильтрация

Отсеивание части объектов можно сделать с помощью метода filter().

Stream.of(1, 2, 3, 4, 5, 6)
        .filter(n -> n > 3) // оставляет только те числа, которые больше 3

Доступ к элементу

Если требуется получить доступ к элементу, никак его при этом не меняя, нам поможет метод peek(). Например, в целях логирования мы хотим вывести значение элемента в консоль.

Stream.of(1, 2, 3, 4, 5, 6)
        .peek(System.out::println)

Удаление дублей

Если в стриме несколько элементов имеют одинаковые значения, а вы хотите получить только уникальные, используйте метод distinct().

Stream.of(2, 2, 3, 2, 3, 3, 2, 2)
        .distinct() // в результате останется только два элемента: [2, 3]

Сортировка

Для сортировки используйте метод sorted(). По умолчанию он использует «натуральный порядок», т.е. сортировку по возрастанию.

Stream.of(2, 1, 3, 5, 4, 6)
        .sorted() // получим [1, 2, 3, 4, 5, 6]

Перегруженная версия этого метода принимает интерфейс Comparator, поэтому вы можете задать свои собственные правила сортировки или воспользоваться готовыми. Приведённый выше пример равносилен следующему:

Stream.of(2, 1, 3, 5, 4, 6)
        .sorted(Comparator.naturalOrder())) // получим [1, 2, 3, 4, 5, 6]

Нетрудно догадаться, что обратную сортировку можно задать таким образом:

Stream.of(2, 1, 3, 5, 4, 6)
        .sorted(Comparator.reverseOrder()) // получим [6, 5, 4, 3, 2, 1]

Ограничение по количеству элементов

Для получения первых N элементов используйте метод limit(). В данном случае мы берём первые 3 элемента:

Stream.of(1, 2, 3, 4, 5, 6)
        .limit(3) // [1, 2, 3]

Пропуск первых элементов

Чтобы пропустить нужное количество первых элементов, используйте метод skip(). Здесь мы пропускаем первые 4 элемента и получаем оставшиеся два:

Stream.of(1, 2, 3, 4, 5, 6)
        .skip(4) // [5, 6]

Обратите внимание, что комбинация методов limit() и skip() позволяет организовать постраничный вывод информации. Например, в пользовательском интерфейсе мы отображаем по две записи на странице. Тогда, если у нас запросят вторую страницу, то выражение будет выглядеть так:

Stream.of(1, 2, 3, 4, 5, 6)
        .skip(2)
        .limit(2) // [3, 4]

Разворачивание многомерных структур

Предположим, у вас есть многомерная структура (двумерный массив элементов типа Integer) и вы хотите его развернуть (сделать «плоским»), просто помещая каждый подмассив в конец результирующего. В этом нам поможет метод flatMap():

Integer[][] array2d = new Integer[][]{{1, 2}, {3, 4}};
Stream<Integer> stream =
        Arrays.stream(array2d).flatMap(Arrays::stream); // [1, 2, 3, 4]

Выводы

В этой статье мы рассмотрели на примерах промежуточные методы Stream API, а во второй части рассмотрим уже терминальные (конечные) методы.


Облако тэгов

Kotlin, Java, Java 16, Java 11, Java 10, Java 9, Java 8, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Hibernate, Collections, Stream API, многопоточность, ввод-вывод, Apache, maven, gradle, JUnit, YouTube, новости, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml

Последние статьи


Комментарии

Добавить комментарий

23.01.2021 12:11 Азамат

Не указано, что промежуточные операции не выполняются без терминальных. То есть тот же
Stream.of(1, 2, 3, 4, 5, 6)
.peek(System.out::println)

Ничего не сделает, если будет выглядеть так.

×

devmark.ru