Использовали ли вы Streams API в Java?
15 марта 2022 г.Прежде чем читать это, я бы порекомендовал попробовать и изучить, что такое императивный и декларативный стили программирования. См. [Императивный против декларативного] (https://ggorantala.dev/imperative-and-declarative-styles-of-programming)
Одной из мощных функций, которую команда Java включила в пакет JDK 1.8, является Streams API.
Целью потоков является обработка последовательности элементов путем выполнения различных операций над элементами.
Новый пакет Java для потоков — java.util.stream.
Что такое поток?
Давайте рассмотрим некоторые важные аспекты Streams API.
- Streams API используется для обработки коллекций объектов.
- Нет хранилища. Поток не является структурой данных, такой как массивы/стеки/очереди и т. д., вместо этого он принимает входные данные из коллекций, массивов или каналов ввода-вывода.
- Потоки не изменяют исходную структуру данных, они только предоставляют результаты в соответствии с конвейерными методами.
- Потоки используются для выполнения сложных операций обработки данных над данными коллекций. Они представляют конвейер, по которому будут проходить данные, и функции для работы с данными.
- В потоках мы используем лямбда-выражения для улучшения библиотеки коллекций, упрощая итерацию по фильтру и извлечение данных из коллекции с помощью потоков.
- Через любой поток может проходить неограниченное количество данных. Данные, полученные из потока, обрабатываются индивидуально по мере поступления.
- Функциональный характер. Операция над потоком производит результат, но не изменяет его источник. Например, фильтрация потока, полученного из коллекции, создает новый поток без отфильтрованных элементов, а не удаление элементов из исходной коллекции.
- Поиск лени. Многие потоковые операции, такие как фильтрация, сопоставление или удаление дубликатов, могут быть реализованы лениво, открывая возможности для оптимизации. Например, «найти первую строку с тремя последовательными гласными» не нужно проверять все входные строки. Потоковые операции делятся на промежуточные (производящие поток) операции и терминальные (производящие ценность или побочные эффекты) операции. Промежуточные операции всегда ленивы.
- Возможно неограниченный. В то время как коллекции имеют конечный размер, потоки в этом не нуждаются. Сокращающие операции, такие как limit(n) или findFirst(), могут позволить выполнять вычисления на бесконечных потоках за конечное время.
- Расходный материал. Элементы потока посещаются только один раз в течение жизни потока. Как и в случае с итератором, необходимо создать новый поток для повторного посещения тех же элементов исходного кода.
Создание потоков
У нас есть несколько разных способов создать поток.
- Из коллекций.
- Из массивов.
- Из произвольного количества объектов.
- Бесконечные и конечные потоки.
Преимущества
Ниже приведены преимущества использования Streams API.
- Мы уже видели разницу между императивным и декларативным подходами. С потоками мы переходим от императивного к декларативному программированию.
- Потоки можно применять только к коллекциям, таким как «список», «карта», «набор», «массивы» и т. д.
- Потоки поощряют меньшую изменчивость
- Они могут работать со своим содержимым параллельно, используя
parallelStream()
.
- Еще одно преимущество/преимущество — потоки лениво обрабатывают данные. Предположим, мы читаем строки текста из большого файла в виде потока, что означает, что поток загружает данные по мере необходимости, что экономит много памяти.
Потоковый конвейер
Хватит говорить! Давайте посмотрим пример 🤩
Давайте посмотрим на пример, чтобы понять потоковый конвейер.
У нас есть список книг, и мы запускаем для него некоторую цепочку методов, таких как filter
, map
и т. д. Эта цепочка вызовов методов называется Stream Pipeline.
Это также называется функциональным программированием, поскольку мы передаем функции.
Book — это POJO с конструктором, геттерами и сеттерами.
```java
учебник {
Заголовок строки;
Автор строки;
Целый год;
Целочисленные копииSoldInMillions;
Двойной рейтинг;
Двойная стоимость в евро;
общедоступная книга (название строки, автор строки, целое число года, целое число копий, проданных в миллионах, двойная оценка, двойная стоимость в евро) {
это.название = название;
этот.автор = автор;
этот.год = год;
this.copiesSoldInMillions = копииSoldInMillions;
this.rating = рейтинг;
this.costInEuros = стоимостьInEuros;
публичная строка getAuthor () {
вернуть автора;
общественный двойной getRating () {
рейтинг возврата;
@Override
общедоступная строка toString () {
вернуть "Книга {" +
"название='" + название + '\'' +
", автор='" + автор + '\'' +
", год=" + год +
", копийПроданоВМиллионах=" + копийПроданоВМиллионах+
", рейтинг=" + рейтинг +
", стоимость в евро = " + стоимость в евро +
Еще один класс BookDatabase для фиктивной инъекции данных.
```java
импортировать java.util.Arrays;
импортировать java.util.List;
открытый класс BookDatabase {
общедоступный статический список<книга> getAllBooks() {
вернуть Arrays.asList(
новая Книга("Дон Кихот", "Мигель де Сервантес", 1605, 500, 3.9, 9.99),
новая книга («Повесть о двух городах», «Чарльз Диккенс», 1859, 200, 3.9, 10.0),
новая книга («Властелин колец», «Дж. Р. Р. Толкин», 2001, 150, 4.0, 12.50),
новая Книга("Маленький принц", "Антуан де Сент-Экзюпери", 2016, 142, 4.4, 5.0),
новая книга («Сон в Красной палате», «Цао Сюэцинь», 1791, 100, 4.2, 10.0)
И, наконец, класс BookApplication
, который выполняет декларативное программирование или неизменность для каждого объекта книги
.
```java
импортировать java.util.List;
открытый класс BookApplication {
public static void main(String[] args) {
List
книги.поток()
.filter(книга -> book.getRating() >= 4)
.map(Книга::getAuthor)
.forEach(System.out::println);
Выход:
```java
Дж.Р.Р. Толкин
Антуан де Сент-Экзюпери
Cao Xueqin
В приведенном выше примере у нас есть список объектов Book.
- Мы применили
.stream(...)
для преобразования списка объектовBook
в поток объектов.
- Мы применили две промежуточные операции
.filter(...)
, которые принимают Predicate и.map(...)
для получения отфильтрованного потока объектов.
- Мы завершили его с помощью
.forEach(...)
, чтобы напечатать все объекты.
Недостатки
- Если потоки не обрабатываются должным образом, они сильно влияют на производительность.
- Кривая обучения требует времени, так как есть много перегруженных методов, которые вам нужно изучить, что сбивает с толку, хотя это не недостаток, но я хочу оставить это здесь как недостаток.
- Впервые опубликовано [здесь] (https://ggorantala.dev/introduction-to-java-streams-api)*
Оригинал