← Назад к вопросам

Какие знаешь операции в Stream API?

2.0 Middle🔥 251 комментариев
#Stream API и функциональное программирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Операции в Stream API Java

Stream API — это мощный функциональный инструмент для работы с коллекциями данных, введённый в Java 8. Он позволяет писать декларативный код вместо императивного.

Общая структура потока

Любая Stream операция следует паттерну:

collection.stream()        // Источник (Source)
    .filter(x -> x > 5)    // Промежуточные операции (Intermediate)
    .map(x -> x * 2)       // Может быть несколько
    .collect(toList());    // Терминальная операция (Terminal)

Промежуточные операции (Lazy)

Эти операции возвращают новый Stream и ленивы — не выполняются, пока не будет вызвана терминальная операция.

1. filter(Predicate) — фильтрация

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
// Результат: [2, 4, 6]

2. map(Function) — преобразование

List<String> names = Arrays.asList("alice", "bob", "charlie");
List<String> uppercase = names.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
// Результат: ["ALICE", "BOB", "CHARLIE"]

3. flatMap(Function) — развёртывание (flatten)

List<List<Integer>> nested = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4),
    Arrays.asList(5, 6)
);
List<Integer> flat = nested.stream()
    .flatMap(List::stream)
    .collect(Collectors.toList());
// Результат: [1, 2, 3, 4, 5, 6]

4. distinct() — удаление дубликатов

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4);
List<Integer> unique = numbers.stream()
    .distinct()
    .collect(Collectors.toList());
// Результат: [1, 2, 3, 4]

5. limit(long) — ограничение количества

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> first3 = numbers.stream()
    .limit(3)
    .collect(Collectors.toList());
// Результат: [1, 2, 3]

6. skip(long) — пропуск элементов

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skipFirst2 = numbers.stream()
    .skip(2)
    .collect(Collectors.toList());
// Результат: [3, 4, 5]

7. sorted() — сортировка

List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9);
List<Integer> sorted = numbers.stream()
    .sorted()
    .collect(Collectors.toList());
// Результат: [1, 2, 5, 8, 9]

// С компаратором
List<String> names = Arrays.asList("charlie", "alice", "bob");
List<String> sortedNames = names.stream()
    .sorted(String::compareTo)
    .collect(Collectors.toList());
// Результат: ["alice", "bob", "charlie"]

8. peek(Consumer) — логирование/отладка

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
    .filter(n -> n > 2)
    .peek(System.out::println)  // Печатает: 3, 4, 5
    .map(n -> n * 2)
    .collect(Collectors.toList());

Терминальные операции (Eager)

Эти операции выполняют вычисления и возвращают конечный результат.

1. collect(Collector) — сбор в коллекцию

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list = numbers.stream().collect(Collectors.toList());
Set<Integer> set = numbers.stream().collect(Collectors.toSet());
Map<Integer, String> map = numbers.stream()
    .collect(Collectors.toMap(n -> n, n -> "num" + n));

2. forEach(Consumer) — итерация

numbers.stream()
    .filter(n -> n > 2)
    .forEach(System.out::println);

3. reduce(BinaryOperator) — свёртка

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
    .reduce(0, Integer::sum);
// Результат: 15

Optional<Integer> product = numbers.stream()
    .reduce((a, b) -> a * b);
// Результат: Optional[120]

4. count() — количество элементов

long count = numbers.stream()
    .filter(n -> n > 2)
    .count();
// Результат: 3

5. findFirst() и findAny() — поиск элемента

Optional<Integer> first = numbers.stream()
    .filter(n -> n > 2)
    .findFirst();
// Результат: Optional[3]

Optional<Integer> any = numbers.parallelStream()
    .filter(n -> n > 2)
    .findAny();

6. 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

7. min() и max() — минимум и максимум

Optional<Integer> minimum = numbers.stream()
    .min(Integer::compare);
// Результат: Optional[1]

Optional<Integer> maximum = numbers.stream()
    .max(Integer::compare);
// Результат: Optional[5]

Практический пример

List<User> users = getUserList();
Map<String, Long> result = users.stream()
    .filter(u -> u.getAge() > 18)                    // Фильтр
    .map(User::getCountry)                           // Преобразование
    .distinct()                                      // Удаление дубликатов
    .collect(Collectors.groupingBy(
        Function.identity(),
        Collectors.counting()                        // Группировка с подсчётом
    ));

Ключевые особенности

  • Ленивость промежуточных операций — не выполняются без терминальной
  • Функциональный стиль — декларативный код
  • Параллельные потокиparallelStream() для многопоточности
  • Иммутабельность — не модифицирует исходную коллекцию