Ответ
Stream API (пакет java.util.stream) — это абстракция для декларативной и функциональной обработки последовательностей данных (коллекций, массивов, I/O каналов), представленная в Java 8.
Ключевые концепции:
- Не хранит данные. Stream — это конвейер операций над источником данных.
- Не изменяет источник. Все операции возвращают новый Stream, оставляя исходную коллекцию неизменной.
- Ленивые (lazy) вычисления. Промежуточные операции (
filter,map) выполняются только при вызове терминальной операции. - Однократная трассировка. Stream нельзя использовать повторно после вызова терминальной операции.
Типы операций:
- Промежуточные (Intermediate): Возвращают
Stream<T>.filter(Predicate<T>)— фильтрация.map(Function<T, R>)— преобразование.sorted(),distinct(),limit(n),skip(n).
- Терминальные (Terminal): Запускают выполнение конвейера и возвращают результат или
void.collect(Collector)— агрегация в коллекцию.forEach(Consumer)— выполнение действия.reduce()— свертка к одному значению.count(),anyMatch(),findFirst().
Примеры:
// 1. Фильтрация и преобразование
List<String> names = List.of("Anna", "Bob", "Alex", "Alice");
List<String> result = names.stream()
.filter(name -> name.startsWith("A")) // Промежуточная
.map(String::toUpperCase) // Промежуточная
.sorted()
.collect(Collectors.toList()); // Терминальная
// result = [ALEX, ALICE, ANNA]
// 2. Работа с примитивами (IntStream, LongStream)
int sum = IntStream.range(1, 10) // 1..9
.filter(x -> x % 2 == 0)
.sum(); // sum = 20
// 3. Параллельная обработка
long count = largeList.parallelStream() // Использует ForkJoinPool
.filter(item -> item.isValid())
.count();
Важные особенности:
- Short-circuit операции:
limit(),findFirst(),anyMatch()могут завершить обработку досрочно. - Порядок в parallel stream: Не гарантируется, если только не используется
forEachOrdered(). - Использование с
Optional: Многие терминальные операции возвращаютOptional(например,findFirst()).