Java Разработка | Spring Boot Backend & Architecture. Программирование на Джава для Developer. IT Собеседования, Алгоритмы и Coding задачи. Уроки и курсы для роста в Tech.

@bookjava
Stream API: Обзор и Основные Методы Stream API – мощный инструмент для обработки данных. Его основные принципы: ✅ Композиция – построение логики из небольших, независимых и чистых функций. ✅ Single Responsibility – каждый шаг выполняет одну конкретную операцию. Такой подход обеспечивает: ✔️ Читаемость кода. ✔️ Отсутствие локальных переменных. ✔️ Линейную последовательность действий. Основные компоненты Stream API Любой поток состоит из трех ключевых частей: 1️⃣ Источник данных (коллекция, массив, файл и т. д.). 2️⃣ Промежуточные преобразования (filter, map и другие). 3️⃣ Конечная операция (коллекционирование, агрегация, перебор). Способы создания стрима Stream можно создать несколькими способами: 🔹 Из коллекции: collection.stream() 🔹 Из массива: Arrays.stream(array) 🔹 Из набора элементов: Stream.of(1, 2, 3) 🔹 Бесконечный поток: Stream.iterate(0, n -> n + 1) 🔹 Бесконечный поток с ограничением (Java 9): Stream.iterate(1, n -> n < 100, n -> n * 2) 🔹 Генерация элементов: Stream.generate(Math::random) 🔹 Диапазон значений: - IntStream.range(1, 5) (1, 2, 3, 4) - IntStream.rangeClosed(1, 5) (1, 2, 3, 4, 5) 🔹 Из файла: Files.lines(Path.of("file.txt")) 🔹 Из строки: "abc".chars() Промежуточные операции Stream API поддерживает множество преобразований. Наиболее распространенные: ✔️ Фильтрация: filter(Predicate<T>) – оставляет только элементы, соответствующие условию. ✔️ Удаление дубликатов: distinct() – исключает повторяющиеся элементы. ✔️ Ограничение количества: limit(n) – берет первые n элементов. ✔️ Сортировка: sorted() – упорядочивает элементы. Менее очевидные операции 🔹 map(Function<T, R>) – применяет функцию к каждому элементу. 🔹 flatMap(Function<T, Stream<R>>) – «разворачивает» элементы из вложенных структур. 🔹 takeWhile(Predicate<T>) (Java 9) – берет элементы, пока выполняется условие. 🔹 dropWhile(Predicate<T>) (Java 9) – пропускает элементы, пока условие выполняется. 🔹 peek(Consumer<T>) – выполняет действие без изменения элементов (удобно для логирования). Конечные операции Стрим начинает обработку данных только при вызове конечной операции: 📌 Коллекционирование: - collect(Collectors.toList()) – собирает в List. - collect(Collectors.toSet()) – собирает в Set. 📌 Поиск элементов: - findFirst() – первый элемент. - findAny() – любой элемент (оптимизирован для параллельных потоков). - anyMatch(Predicate<T>) – хотя бы один элемент удовлетворяет условию. - allMatch(Predicate<T>) – все элементы удовлетворяют условию. - noneMatch(Predicate<T>) – ни один элемент не удовлетворяет условию. 📌 Агрегация: - min(Comparator<T>) – минимальный элемент. - max(Comparator<T>) – максимальный элемент. - count() – количество элементов. - reduce(BinaryOperator<T>) – свертка элементов в одно значение. 📌 Побочные эффекты: - forEach(Consumer<T>) – выполняет действие над каждым элементом. - forEachOrdered(Consumer<T>) – выполняет действие, сохраняя порядок (важно для параллельных потоков). Особенности работы со Stream API 1️⃣ Стрим – это не структура данных Он лишь обходит источник, выполняя операции лениво. 2️⃣ Стрим нельзя использовать повторно После вызова конечной операции повторное использование потока приведет к IllegalStateException. 3️⃣ Исходные данные не изменяются Методы Stream API не модифицируют исходную коллекцию. Разбор сложных случаев ❌ Ошибочный код: Stream.of(-1, 0, 1).max(Math::max).get(); ✅ Почему ошибка? Метод max() принимает Comparator<T>, но Math.max(a, b) – это BiFunction<Integer, Integer, Integer>. Они не эквивалентны! ℹ️ Решение: Stream.of(-1, 0, 1).max(Integer::compareTo).get(); // Вернет 1 👉 @BookJava
Если у вас установлено приложение,
вы можете сразу перейти в канал