Какие терминальные операции есть в Java Stream API?

«Какие терминальные операции есть в Java Stream API?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Терминальные операции завершают поток и возвращают результат (не поток). Они "потребляют" поток.

Основные терминальные операции:

  • forEach(Consumer) — выполняет действие для каждого элемента. Порядок не гарантирован в параллельных потоках.
  • forEachOrdered(Consumer) — выполняет действие с сохранением порядка, даже в параллельных потоках.
  • collect(Collector) — собирает элементы в коллекцию или другой объект. Самый гибкий метод.
    List<String> list = stream.collect(Collectors.toList());
    Map<String, Integer> map = stream.collect(Collectors.toMap(k -> k, v -> v.length()));
  • toArray() — возвращает массив элементов потока.
  • reduce(...) — сводит элементы к одному значению (аккумулятор).
    Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
  • min(Comparator) / max(Comparator) — возвращают минимальный/максимальный элемент (Optional).
  • count() — возвращает количество элементов в потоке (long).
  • anyMatch(Predicate) / allMatch(Predicate) / noneMatch(Predicate) — проверяют, соответствует ли поток условию (хотя бы один, все, ни один). Возвращают boolean.
  • findFirst() / findAny() — возвращают первый/любой элемент потока (Optional). findAny() эффективнее в параллельных потоках.

Пример:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0); // true
long count = numbers.stream().filter(n -> n > 2).count(); // 3
Optional<Integer> first = numbers.stream().findFirst(); // Optional[1]