Ответ
В Java Stream API операции делятся на промежуточные (intermediate) и терминальные (terminal), что определяет их поведение в цепочке вызовов.
Промежуточные операции (например, filter(), map(), sorted(), distinct()):
- Ленивые (lazy) — не выполняют обработку немедленно, а лишь добавляют новую операцию в конвейер.
- Возвращают новый
Stream, что позволяет строить цепочки (pipeline). - Обработка данных начинается только при вызове терминальной операции.
Терминальные операции (например, collect(), forEach(), reduce(), count(), anyMatch()):
- Энергичные (eager) — запускают выполнение всего конвейера, обрабатывают элементы и производят результат или побочный эффект.
- Возвращают не
Stream, а конкретное значение (void,Optional,List,booleanи т.д.). - После вызова терминальной операции поток считается потребленным и не может быть использован повторно.
Пример:
List<String> result = names.stream() // Источник потока
.filter(name -> name.length() > 3) // Промежуточная операция: фильтрация
.map(String::toUpperCase) // Промежуточная операция: преобразование
.collect(Collectors.toList()); // Терминальная операция: сбор в список
В этом примере filter и map лишь настраивают конвейер. Фактический обход коллекции names, применение фильтра и маппера происходит внутри вызова collect().