Пакет java.util.stream – это средства потоковой обработки данных в функциональном стиле. Они не имеют ничего общего (кроме названия) с потоками ввода-вывода. Типичные применения – конвертация, переупаковка, и агрегация данных.

Три основных понятия Java Stream API – источник данных, промежуточная (intermediate), и терминальная (terminal) операции.

Источником может быть заранее заданный набор данных, или динамический генератор, возможно даже бесконечный. Сам источник никогда не модифицируется последующими операциями.

Промежуточные операции модифицируют стрим. На одном потоке можно вызвать сколько угодно промежуточных операций.

Терминальная операция «потребляет» поток. Она может быть только одна, в конце работы с отдельно взятым стримом. Стримы работают лениво – вся цепочка промежуточных операций не начнет выполняться до вызова терминальной.

Типичный пример использования стримов – map-reduce. Map – промежуточная операция, reduce – терминальная.

Источники и промежуточные операции могут изменять набор характеристик потока, которые влияют на дальнейшую обработку. Операция может иметь свойства – элементы перечисления StreamOpFlag:
SORTED – можно сравнивать элементы;
ORDERED – определен порядок обхода;
DISTINCT – содержит уникальные элементы, без дублей;
SIZED – имеет определенный размер;
SHORT_CIRCUIT – операция, которая может приводить к короткому замыканию.

Для лучшего погружения рекомендуется к просмотру доклад Тагира Валеева.