Приведите примеры методов для каждого типа операций Stream API в Java.

Ответ

Stream API в Java предоставляет несколько типов операций. Вот ключевые примеры:

1. Промежуточные операции (Intermediate):

  • filter(Predicate<T>) — фильтрация по условию.
    List<Integer> evens = Stream.of(1, 2, 3, 4)
        .filter(n -> n % 2 == 0)
        .collect(Collectors.toList()); // [2, 4]
  • map(Function<T, R>) — преобразование каждого элемента.
    List<Integer> lengths = Stream.of("Java", "Stream")
        .map(String::length)
        .collect(Collectors.toList()); // [4, 6]
  • sorted() / sorted(Comparator<T>) — сортировка.
    List<String> sorted = Stream.of("Beta", "Alpha")
        .sorted()
        .collect(Collectors.toList()); // ["Alpha", "Beta"]
  • distinct() — удаление дубликатов.
  • limit(long n) — ограничение количества элементов.

2. Терминальные операции (Terminal):

  • reduce(BinaryOperator<T>) — свертка элементов в одно значение.
    Optional<Integer> sum = Stream.of(1, 2, 3)
        .reduce(Integer::sum); // Optional[6]
  • collect(Collector) — сбор элементов в коллекцию или другую структуру.
  • forEach(Consumer<T>) — выполнение действия для каждого элемента.
  • count() — подсчет количества элементов.

Важно: Промежуточные операции «ленивы» и выполняются только при вызове терминальной операции.

Ответ 18+ 🔞

А, Stream API, говоришь? Ну это ж, блядь, как конвейер на заводе, только для данных, а не для гаек! Сейчас разжую, как есть, без соплей.

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

Первая банда — Промежуточные операции (Intermediate). Они просто болтаются в трубе и ждут своего часа. Ленивые, сука, как коты.

  • filter(Predicate<T>) — Это как сито, ёпта. Просеивает только то, что по условию проходит.

    List<Integer> evens = Stream.of(1, 2, 3, 4)
        .filter(n -> n % 2 == 0) // Оставляем только чётные, остальные — в мусорку
        .collect(Collectors.toList()); // [2, 4]
  • map(Function<T, R>) — Трансформер, блядь. Берёт один предмет, выхуячивает из него другой. Строку в число, объект в его поле — что угодно.

    List<Integer> lengths = Stream.of("Java", "Stream")
        .map(String::length) // Берём слово, выдаём его длину. "Java" -> 4
        .collect(Collectors.toList()); // [4, 6]
  • sorted() — Сортировочка. Всё по полочкам расставляет. Можно свой порядок указать, если стандартный не нравится.

    List<String> sorted = Stream.of("Beta", "Alpha")
        .sorted() // Всё по алфавиту, как в детсаду
        .collect(Collectors.toList()); // ["Alpha", "Beta"]
  • distinct() — Уникализатор. Убирает повторы, оставляет только по одному экземпляру. Как будто сетью прошёлся.

  • limit(long n) — Жадина. Берёт только первые N штук, а на остальные кладёт болт.

Вторая банда — Терминальные операции (Terminal). Вот они-то и есть тот самый насос, который включает весь этот конвейер. Без них — тишина и пиздец.

  • reduce(BinaryOperator<T>) — Свёрточка. Берёт все элементы и склеивает в один, как в мясорубке.

    Optional<Integer> sum = Stream.of(1, 2, 3)
        .reduce(Integer::sum); // 1 + 2 + 3 = 6. Всё, Optional[6]
  • collect(Collector) — Сборщик-упаковщик. Результаты из потока собирает в кучу — в список, в сет, в мапу, да куда захочешь.

  • forEach(Consumer<T>) — Действователь. Просто берёт и делает что-то с каждым элементом. Вывод на экран, например. Безвозвратный, обычно.

  • count() — Счётчик. Просто говорит, сколько там всего наконец-то натекло.

Запомни главное, чтобы не облажаться: Все эти промежуточные штуки — они дохуя ленивые. Ты можешь навешать filter, map и sorted друг на друга пачкой, но пока ты не вызовешь в конце collect или reduce — нихуя не произойдёт, вычисления даже не начнутся. Это как составить список дел и не сделать ни одного. Пиздец, да?