Ответ
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 — нихуя не произойдёт, вычисления даже не начнутся. Это как составить список дел и не сделать ни одного. Пиздец, да?