Что такое Stream API в Java?

Ответ

Stream API — это набор классов и интерфейсов в Java (начиная с версии 8) для декларативной обработки последовательностей данных (коллекций, массивов, I/O источников) в функциональном стиле.

Ключевые принципы:

  • Неизменяемость источника: Операции над Stream не изменяют исходную коллекцию.
  • Ленивые вычисления: Промежуточные операции (например, filter, map) выполняются только при вызове терминальной операции.
  • Однократное использование: Stream нельзя использовать повторно после вызова терминальной операции.
  • Поддержка параллелизма: Легко переключиться на параллельную обработку с помощью .parallelStream() или .parallel().

Типы операций:

  1. Промежуточные (Intermediate): Возвращают новый Stream.
    • filter(Predicate<T>) — фильтрация по условию.
    • map(Function<T, R>) — преобразование каждого элемента.
    • sorted() — сортировка.
    • distinct() — удаление дубликатов.
  2. Терминальные (Terminal): Запускают обработку и возвращают результат (не Stream).
    • collect(Collector) — собирает элементы в коллекцию или строку.
    • forEach(Consumer) — выполняет действие для каждого элемента.
    • count(), min(), max(), reduce() — агрегатные функции.

Пример:

List<String> names = Arrays.asList("Anna", "Bob", "Alice", "Alex");
List<String> result = names.stream()          // Создание потока
        .filter(name -> name.startsWith("A")) // Промежуточная: фильтр
        .map(String::toUpperCase)             // Промежуточная: преобразование
        .sorted()                             // Промежуточная: сортировка
        .collect(Collectors.toList());        // Терминальная: сбор в список
// Результат: [ALEX, ALICE, ANNA]

Зачем это нужно? Stream API делает код более читаемым, выразительным и упрощает реализацию параллельных вычислений.

Ответ 18+ 🔞

Да ты посмотри на эту штуку, Stream API, блядь! Это ж как в сказке про Герасима, только наоборот — не топить, а вытаскивать данные, сука, из коллекций, да так, чтобы всё красиво и по-новому!

Представь, раньше ты, как этот немой силач, тупо циклы крутил, for-ами всё перебирал, пот прошибает, а результат — хуй с горы. А тут, ёпта, приходит Stream API, и говорит: «Мужик, расслабься, блядь! Смотри, как надо!»

В чём соль, блядь?

  • Исходник не трогаем! Это святое, как та самая барыня у Тургенева. Поток данные не портит, а работает с копией, в рот меня чих-пых! Сделал что хотел, а коллекция-мать цела.
  • Ленивый, как кот собака! Пока ты не скажешь «ну-ка давай, сука, результат!», он нихрена не делает. Все эти filter и map висят в воздухе, ждут команды.
  • Одноразовый, как... ну ты понял. Использовал — выкинул. Хочешь ещё — новый создавай, пидарас шерстяной.
  • Параллелизм на раз-два. Щёлкнул .parallel() — и понеслась душа в рай, все ядра процессора в дело, овердохуища скорости!

Что он умеет, этот хитрожопый поток? Две главные штуки: промежуточные операции (они поток готовят) и терминальные (они из него результат выжимают).

  1. Промежуточные (готовят почву):

    • filter(...) — отсеивает мусор, как Герасим метлой. «Ты — Anna? Проходи. Ты — Bob? Иди нахуй, не начинается с A».
    • map(...) — превращает одно в другое. Был «Alex», стал «ALEX». Магия, блядь!
    • sorted() — строит по струнке, чтоб не дерзили.
    • distinct() — выкидывает близнецов, оставляет уникальных.
  2. Терминальные (добивают, как та Муму):

    • collect(...) — собирает всё добро в мешок (список, сет, строку).
    • forEach(...) — делает с каждым что скажешь.
    • count(), min(), max() — считает, ищет самого маленького и большого.
    • reduce(...) — сводит всё к одному значению, типа суммы.

Смотри, как это выглядит в деле, ёбана:

List<String> names = Arrays.asList("Anna", "Bob", "Alice", "Alex");
List<String> result = names.stream()          // Запустили поток, поехали!
        .filter(name -> name.startsWith("A")) // Отфильтровали этих, на букву "А"
        .map(String::toUpperCase)             // Перевели всех на крик (в верхний регистр)
        .sorted()                             // Построили по алфавиту, чтоб не толкались
        .collect(Collectors.toList());        // И собрали в новый список, готово!
// И что получили? [ALEX, ALICE, ANNA]! Красота, блядь!

А зачем это всё, спрашиваешь? Да чтобы не быть, как тот Герасим, который только «Му-му» мычать может! Код становится чистый, читаемый, как стихи Тургенева, только без утоплений. И если надо ускориться — просто параллельный поток включил, и всё, пидары налетели на данные со всех ядер! Вообще песня, а не технология!