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

Базовый Java
≈ 2 мин чтения

Терминальная операция запускает pipeline

Пока у цепочки есть только промежуточные операции, она лишь описывает будущую работу. Терминальная операция запускает обработку и завершает stream. После неё тот же stream повторно использовать нельзя.

Получить коллекцию, количество или выполнить действие

toList() собирает элементы в список, count() возвращает их количество, а forEach() выполняет действие для элементов.

List<String> names = List.of("Ann", "Bob", "Alexander");

long count = names.stream()
        .filter(name -> name.length() > 3)
        .count();

Результат count равен 1. Если нужен именно список, ту же цепочку можно закончить вызовом toList().

Проверки и поиск могут завершиться раньше

anyMatch, allMatch и noneMatch проверяют элементы по условию. findFirst и findAny ищут элемент. Эти операции не обязаны проходить весь stream, если ответ уже известен.

boolean hasLongName = names.stream()
        .anyMatch(name -> name.length() > 8);

Как только находится подходящая строка, дальнейший проход может не понадобиться. Результат поиска возвращается через Optional, потому что подходящего элемента может не быть. Сам Optional подробно разберём позже в этом разделе.

min, max и reduce сворачивают элементы

min и max находят крайний элемент по Comparator. reduce последовательно объединяет элементы в один результат.

int sum = Stream.of(3, 5, 7)
        .reduce(0, Integer::sum);

Начальное значение здесь равно 0, а каждый следующий элемент складывается с накопленным результатом. Для сумм чисел позже увидим более прямые операции примитивных stream, но reduce показывает общую идею свёртки.

Терминальная операция завершает stream. Если после неё нужна другая обработка тех же исходных данных, создай новый stream из источника, а не пытайся переиспользовать старый.