← Назад к вопросам
Какие знаешь два типа методов у Stream?
1.0 Junior🔥 191 комментариев
#Stream API и функциональное программирование
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Два типа методов Stream API в Java
Stream API в Java содержит два принципиально различных типа методов, которые различаются по своему назначению и возвращаемому значению.
1. Промежуточные операции (Intermediate Operations)
Это методы, которые возвращают новый Stream и позволяют выполнять цепочку операций. Они ленивы (lazy) — выполняются только при вызове терминальной операции.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// Промежуточные операции не выполняются в этой строке!
Stream<Integer> stream = numbers.stream()
.filter(n -> n > 2) // Intermediate
.map(n -> n * 2) // Intermediate
.distinct(); // Intermediate
// Выполнятся только при вызове терминальной операции
List<Integer> result = stream.collect(Collectors.toList());
Основные промежуточные операции:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// filter — оставляет только элементы, соответствующие предикату
Stream<Integer> filtered = numbers.stream()
.filter(n -> n % 2 == 0); // Результат: [2, 4, 6]
// map — преобразует каждый элемент
Stream<Integer> mapped = numbers.stream()
.map(n -> n * 10); // Результат: [10, 20, 30, 40, 50, 60]
// flatMap — преобразует в Stream и объединяет
Stream<Integer> flattened = numbers.stream()
.flatMap(n -> Stream.of(n, n * 2)); // Развёртывает вложенные потоки
// distinct — удаляет дубликаты
Stream<Integer> unique = numbers.stream()
.distinct();
// sorted — сортирует элементы
Stream<Integer> sorted = numbers.stream()
.sorted(); // Можно передать компаратор: .sorted(Comparator.reverseOrder())
// limit — ограничивает количество элементов
Stream<Integer> limited = numbers.stream()
.limit(3); // Результат: [1, 2, 3]
// skip — пропускает первые N элементов
Stream<Integer> skipped = numbers.stream()
.skip(2); // Результат: [3, 4, 5, 6]
// peek — побочная операция для отладки
Stream<Integer> peeked = numbers.stream()
.peek(n -> System.out.println("Processing: " + n))
.filter(n -> n > 2);
2. Терминальные операции (Terminal Operations)
Это методы, которые завершают цепочку операций и возвращают конкретный результат (не Stream). После вызова терминальной операции Stream закрывается и больше не может быть использован.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// forEach — выполняет действие для каждого элемента (void)
integers.stream()
.forEach(n -> System.out.println(n));
// collect — собирает элементы в коллекцию
List<Integer> collected = numbers.stream()
.collect(Collectors.toList());
// count — подсчитывает количество элементов
long count = numbers.stream()
.count(); // Результат: 6
// findFirst — возвращает первый элемент
Optional<Integer> first = numbers.stream()
.findFirst(); // Результат: Optional[1]
// findAny — возвращает любой элемент
Optional<Integer> any = numbers.stream()
.findAny();
// reduce — объединяет элементы в один
Optional<Integer> sum = numbers.stream()
.reduce((a, b) -> a + b); // Результат: Optional[21]
// min/max — находит минимум/максимум
Optional<Integer> min = numbers.stream()
.min(Comparator.naturalOrder());
Optional<Integer> max = numbers.stream()
.max(Comparator.naturalOrder());
// anyMatch/allMatch/noneMatch — проверяет условие
boolean hasEven = numbers.stream()
.anyMatch(n -> n % 2 == 0); // true
boolean allPositive = numbers.stream()
.allMatch(n -> n > 0); // true
boolean noNegative = numbers.stream()
.noneMatch(n -> n < 0); // true
Практический пример
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Alice");
List<String> result = names.stream()
// Промежуточные операции (ленивы)
.filter(name -> name.length() > 3) // [Alice, Charlie, David, Alice]
.map(String::toUpperCase) // [ALICE, CHARLIE, DAVID, ALICE]
.distinct() // [ALICE, CHARLIE, DAVID]
.sorted() // [ALICE, CHARLIE, DAVID]
// Терминальная операция (выполняет всю цепочку)
.collect(Collectors.toList()); // Результат: [ALICE, CHARLIE, DAVID]
Ключевое отличие: промежуточные операции создают новые Stream и позволяют чейнить методы, а терминальные операции завершают обработку и возвращают конкретный результат.