Статьи Утилиты Telegram YouTube RuTube Отзывы

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

7 апреля 2019

Тэги: Collections, Java, 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, а во второй части рассмотрим уже терминальные (конечные) методы.



Комментарии

23.01.2021 12:11 Азамат

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

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

25.07.2024 19:08 Максим

Спасибо! Все доступно и интересно

30.09.2024 10:15

внатуре без терминалки peek не запустится. проверено.

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

×

devmark.ru