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

Приведи пример промежуточных операций в Stream API

2.0 Middle🔥 201 комментариев
#Другое

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Примеры промежуточных операций в Stream API

Промежуточные операции в Stream API — это операции, которые преобразуют поток и возвращают новый поток, позволяя строить цепочки обработки данных. Они ленивые — выполняются только при вызове терминальной операции. Вот основные категории и примеры.

1. Фильтрация и выборка

List<String> names = Arrays.asList("Анна", "Иван", "Мария", "Петр", "Алексей");

// filter: отбирает элементы по условию
List<String> startWithA = names.stream()
    .filter(name -> name.startsWith("А"))
    .collect(Collectors.toList()); // ["Анна", "Алексей"]

// distinct: удаляет дубликаты
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> unique = numbers.stream()
    .distinct()
    .collect(Collectors.toList()); // [1, 2, 3, 4, 5]

2. Преобразование элементов

// map: преобразует каждый элемент
List<String> upperNames = names.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList()); // ["АННА", "ИВАН", "МАРИЯ"...]

// flatMap: "разворачивает" вложенные структуры
List<List<String>> nestedList = Arrays.asList(
    Arrays.asList("a", "b"),
    Arrays.asList("c", "d")
);
List<String> flat = nestedList.stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList()); // ["a", "b", "c", "d"]

3. Ограничение и пропуск элементов

List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);

// limit: ограничивает количество элементов
List<Integer> firstThree = nums.stream()
    .limit(3)
    .collect(Collectors.toList()); // [1, 2, 3]

// skip: пропускает первые N элементов
List<Integer> afterThird = nums.stream()
    .skip(3)
    .collect(Collectors.toList()); // [4, 5, 6, 7, 8]

4. Сортировка

// sorted: сортировка элементов
List<String> sortedNames = names.stream()
    .sorted()
    .collect(Collectors.toList()); // ["Алексей", "Анна", "Иван", "Мария", "Петр"]

// sorted с компаратором
List<String> byLength = names.stream()
    .sorted(Comparator.comparingInt(String::length))
    .collect(Collectors.toList()); // ["Иван", "Петр", "Анна", "Мария", "Алексей"]

5. Отладка и просмотр элементов

// peek: выполняет действие для каждого элемента без изменения
List<String> processed = names.stream()
    .filter(name -> name.length() > 4)
    .peek(name -> System.out.println("Отфильтровано: " + name))
    .map(String::toUpperCase)
    .collect(Collectors.toList());

Комбинированный пример

Вот практический пример, демонстрирующий цепочку промежуточных операций:

List<Employee> employees = Arrays.asList(
    new Employee("Иван", 25, 50000),
    new Employee("Мария", 30, 60000),
    new Employee("Алексей", 25, 55000),
    new Employee("Ольга", 35, 70000)
);

List<String> result = employees.stream()
    // 1. Фильтрация: возраст < 30
    .filter(emp -> emp.getAge() < 30)
    // 2. Сортировка: по зарплате по убыванию
    .sorted(Comparator.comparingInt(Employee::getSalary).reversed())
    // 3. Преобразование: в строки
    .map(emp -> emp.getName() + " - " + emp.getSalary())
    // 4. Пропуск первого
    .skip(1)
    // 5. Ограничение вывода
    .limit(2)
    .collect(Collectors.toList());

// Результат: ["Алексей - 55000", "Иван - 50000"]

Важные особенности промежуточных операций:

  • Ленивость: Вычисления происходят только при вызове терминальной операции
  • Без состояния: Большинство операций (filter, map) не зависят от предыдущих элементов
  • С состоянием: Некоторые операции (sorted, distinct) требуют знания всех элементов
  • Конвейерность: Операции объединяются в конвейер, минимизируя проходы по данным

Эти операции составляют основу функционального стиля обработки коллекций в Java, делая код более декларативным и читаемым. Правильное комбинирование промежуточных операций позволяет эффективно решать сложные задачи обработки данных с минимальным написанием кода.