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

Терминальные операции Stream API

8 апреля 2019

Тэги: Collections, Java, Stream API.

Содержание

  1. Преобразование в коллекцию
  2. Итерация по элементам
  3. Подсчёт количества элементов
  4. Минимальное и максимальное значения
  5. Поиск первого подходящего элемента
  6. Соответствие всех элементов
  7. Полное несоответствие
  8. Соответствие хотя бы одного элемента

Ранее мы уже рассмотрели Промежуточные операции Stream API, а сейчас рассмотрим терминальные (конечные).

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

Преобразование в коллекцию

Самая распространённая терминальная операция collect(). Результатом может быть, например, список.

List<String> fruits = Stream.of("apple", "banana", "lemon", "orange")
        // здесь могут быть ещё какие-то преобразования
        .collect(Collectors.toList());

А можно преобразовать стрим из строк в мапу, причём ключом сделать первую букву соответствующего слова:

Map<String, String> fruits = Stream.of("apple", "banana", "lemon", "orange")
        .collect(Collectors.toMap(e -> e.substring(0, 1), e -> e));
        // {a=apple, b=banana, l=lemon, o=orange}

Итерация по элементам

Простой обход элементов стрима можно выполнить с помощью метода forEach(). Его смысл полностью аналогичен языковой конструкции for.

Stream.of(5, 3, 2, 10, 8).forEach(System.out::println);

Здесь мы просто выводим в консоль значение каждого элемента стрима.

Подсчёт количества элементов

Аналог метода size() в коллекциях и поля length в массивах. В стримах для этого используется метод count(). Обратите внимание, что метод возвращает не int, а long.

long count = Stream.of("apple", "banana", "lemon", "orange")
        .count(); // 4

Минимальное и максимальное значения

Как нетрудно догадаться, min() возвращает минимальное значение, а max() – максимальное. В качестве параметра они принимают класс Comparator.

Также обратите внимание, как мы обошли «одноразовость» потока. Чтобы не писать два раза конструкцию Stream.of(...), мы использовали утилитарный класс Supplier<>. Вызов метода get() у него в действительности каждый раз создаёт новый поток с одними и теми же значениями.

Supplier<Stream<Integer>> streamSupplier = () -> Stream.of(5, 3, 2, 10, 8);
Optional<Integer> min = streamSupplier.get().min(Comparator.naturalOrder()); // Optional[2]
Optional<Integer> max = streamSupplier.get().max(Comparator.naturalOrder()); // Optional[10]

Поиск первого подходящего элемента

Метод findFirst() возвращает первый элемент стрима. Этот метод очень удобно использовать в паре с filter().

Optional<Integer> first = Stream.of(1, 2, 3, 4, 5)
        .filter(e -> e % 2 == 0)
        .findFirst(); // Optional[2]

В данном случае мы вернём первое чётное число, т.е. 2.

Соответствие всех элементов

Чтобы проверить все элементы стрима на соответствие некоторому условию, используйте метод allMatch(). Его результатом может быть только true или false.

boolean isAllPositive = Stream.of(1, 2, 3, 4, 5)
        .allMatch(e -> e > 0); // true

В этом примере мы проверяем, что все элементы положительные.

Полное несоответствие

Если нужно проверить, что ни один элемент не удовлетворяет условию, воспользуйтесь методом noneMatch(). Перепишем предыдущий пример так:

boolean isAllPositive = Stream.of(1, 2, 3, 4, 5)
        .noneMatch(e -> e < 0); // true

Соответствие хотя бы одного элемента

Чтобы проверить наличие хотя бы одного элемента, удовлетворяющего условию, используйте метод anyMatch().

boolean hasNegative = Stream.of(1, 2, 3, 4, 5)
        .anyMatch(e -> e < 0); // false


Комментарии

08.03.2022 12:21 Alex

А как же метод reduce?

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

×

devmark.ru