Потоки данных. Stream API. Общая информация
Перед изучением данной темы рекомендуется ознакомиться со следующими темами:
- Обобщения. Параметризованные типы. Обобщенные классы интерфейсы, методы
- Лямбда-выражения. Основные понятия. Функциональный интерфейс. Примеры
- Стандартные (предопределенные) функциональные интерфейсы Java
Содержание
- 1. Прикладной потоковый интерфейс Stream API. Характерные особенности
- 2. Поток данных. Определение
- 3. Интерфейсы из пакета java.util.stream
- Связанные темы
Поиск на других ресурсах:
1. Прикладной потоковый интерфейс Stream API. Характерные особенности
Начиная с версии JDK 8 в языке Java были введены средства работы с потоками данных, которые получили название прикладной потоковый интерфейс API (Stream Application Programming Interface). Работа со средствами Stream API базируется на использовании лямбда-выражений.
Характерными особенностями этого интерфейса является использование различных операций над потоками данных. К этим операциям можно отнести:
- поиск данных;
- модификация данных;
- фильтрование потока данных для получения нового потока;
- сортировка данных;
- другие разнообразные манипуляции над данными.
Операции над потоками данных выполняются на основе формирования соответствующих запросов. Интерфейс Stream API хорошо подходит для обработки больших массивов данных с применением механизмов распараллеливания.
⇑
2. Поток данных. Определение
Под понятием «поток данных» подразумевается канал передачи данных. Для потока данных определяется понятие источника данных. Источниками данных могут быть массив, коллекция, список и тому подобное. Поток данных оперирует этими источниками. Поток данных еще можно определить как последовательность объектов.
В самом потоке данные не сохраняются, а только перемещаются при их обработке (фильтровании, сортировке и т.д.). При обработке потока данных источник данных не изменяется. Это означает, что при сортировке данных создается новый отсортированный поток данных, а начальный источник остается несортированным.
⇑
3. Интерфейсы из пакета java.util.stream
3.1. Интерфейс BaseStream. Методы
Средства работы с потоками данных Stream API являются составляющей пакета java.util.stream. Данный пакет содержит набор потоковых интерфейсов, образующих иерархию.
Базовым поточным интерфейсом является BaseStream, который имеет следующее объявление
interface BaseStream<T, S extends BaseStream<T, S>>
здесь
- T – тип элементов в потоке данных;
- S – тип потока данных, который расширяет интерфейс BaseStream.
В интерфейсе BaseStream объявляется ряд методов, перечисленных ниже.
1. Закрыть поток данных
void close()
Метод закрывает вызывающий поток данных. Обязательно нужно закрывать потоки данных, связанные с файлами.
2. Определить, является ли параллельным поток данных
boolean isParallel()
Метод возвращает true, если поток данных есть параллельным.
3. Получить итератор для потока данных
Iterator<T> iterator()
здесь
- T – тип элементов потока данных.
Метод получает итератор для потока данных и возвращает ссылку на него. Метод является конечной операцией.
4. Задать обработчик события закрытия потока.
S onClose(Runnable handler)
здесь
- S – тип новосозданного потока данных;
- handler – метод, содержащий код, который должен выполниться при закрытии потока.
Метод onClose() возвращает новый поток данных с заданным обработчиком события закрытия. Указанный обработчик вызывается при закрытии потока данных. Метод является промежуточной операцией.
5. Вернуть паралельный поток данных
S parallel()
здесь
- S – тип новосозданного параллельного потока данных.
Метод возвращает параллельный поток данных основываясь на вызывающем потоке данных. Если вызывающий поток данных является параллельным, то он и возвращается. Это промежуточная операция.
6. Вернуть последовательный поток данных
S sequential()
здесь
- S – тип новосозданного последовательного потока данных.
Метод возвращает последовательный поток данных на основе вызывающего потока данных. Если вызывающий поток данных уже является последовательным, то этот поток и возвращается.
Метод является промежуточной операцией.
7. Получить итератор-разделитель
Spliterator<T> spliterator()
здесь
- T – тип элементов потока данных.
Метод получает итератор-разделитель для потока данных и возвращает ссылку на него. Метод является конечной операцией.
8. Вернуть неупорядоченный поток данных
S unordered()
здесь
- S – тип результирующего неупорядоченного потока данных.
Метод возвращает неупорядоченный поток данных на основе вызывающего потока данных. Если вызывающий поток данных уже есть неупорядоченным, то именно он и возвращается. Метод является промежуточной операцией.
⇑
3.2. Интерфейс Stream. Обзор методов
От базового интерфейса BaseStream унаследованы несколько интерфейсов. Наиболее употребительным из них является обобщенный интерфейс Stream<T>, который имеет следующее объявление
interface Stream<T>
здесь
- T – тип элементов в потоке данных.
В интерфейсе Stream<T> определяется ряд методов, которые можно использовать при обработке потоков данных. Эти методы описываются далее.
1. Накопить элементы в контейнере
<R, A> R collect(Collector<? super T, A, R> collector)
здесь
- R – тип контейнера, в котором накапливаются элементы;
- T – тип елемента из вызывающего потока данных;
- A – внутренний накопительный тип;
- collector – функция накопления, которая представлена лямбда-выражением. Функция определяет порядок выполнения процесса накопления.
Метод реализует операцию изменяемого сведения. Метод накапливает элементы в изменяющемся контейнере и возвращает этот контейнер.
Метод collect() является конечной операцией.
2. Получить количество элементов в потоке
long count()
Метод count() есть конечной операцией.
3. Выработать новый поток данных по заданному фильтру
Stream<T> filter(Predicate<? super T> predicate)
тут
- T – тип элементов потока данных;
- predicate – условие, по которому формируется новый поток данных.
Метод filter() есть промежуточной операцией.
4. Выполнить действие над каждым элементом потока данных
void forEach(Consumer<? super T> action)
здесь
- action — ссылка на стандартный функциональный интерфейс Consumer<T>. В интерфейсе Consumer<T> реализован метод, который выполняет некоторое действие над элементом типа T. Это действие будет применяться к каждому элементу потока данных.
Метод forEach() есть конечной операцией.
5. Применить указанную функцию отображения для обобщенного типа R
<R> Stream<R> map(Function<? super T, ? extends R> map_function)
тут
- map_function – функция отображения, которая применяется к элементам из вызывающего потока данных. Результатом работы функции есть новый поток данных, который содержит эти элементы.
Это промежуточная операция.
6. Применить функцию отображения для потока типа DoubleStream
DoubleStream mapToDouble(ToDoubleFunctin <? super T> map_function)
здесь
- map_function — функция отображения, которая применяется к элементам вызывающего потока данных.
Результатом работы функции mapToDouble() является новый поток данных типа DoubleStream. Тип элементов в потоке устанавливается Double. Это промежуточная операция.
7. Применить функцию отображения для потока типа IntStream
IntStream mapToInt(ToIntFunctin <? super T> map_function)
здесь
- map_function — функция отображения, которая применяется к элементам вызывающего потока данных.
Результатом работы функции mapToInt() является новый поток данных типа IntStream. Тип элементов в потоке устанавливается Integer. Это промежуточная операция.
8. Применить функцию отображения для потока типа LongStream
LongStream mapToLong(ToLongFunctin <? super T> map_function)
здесь
- map_function — функция отображения, которая применяется к элементам вызывающего потока данных.
На основе заданной функции отображения создается новый поток данных типа LongStream содержащий эти элементы. Это промежуточная операция.
9. Поиск минимального значения в потоке данных типа T
Optional<T> min(Comparator<? super T> comparator)
здесь
- comparator — ссылка на метод, в котором описывается код сравнения двух элементов типа T. По коду этого метода определяется элемент с минимальным значением в потоке данных.
Метод min() является конечной операцией.
10. Поиск максимального значения в потоке данных типа T
Optional<T> max(Comparator<? super T> comparator)
здесь
- comparator — ссылка на метод, в котором описывается код сравнения двух элементов типа T. На основе кода этого метода определяется элемент с максимальным значением в потоке данных.
Метод max() есть конечной операцией.
11. Реализовать сведение для элементов в вызывающем потоке данных
T reduce (T identityVal, BinaryOperator<T> storage)
здесь
- identityVal — значение идентичности, которое используется в сочетании с функцией storage, для получения такого же элемента без изменений;
- storage — функция, которая оперирует двумя значениями типа T и возвращает результат.
Метод reduce() является конечной операцией.
12. Сортировка потока данных
Stream<T> sorted()
Метод sorted() предназначен для сортировки потока данных в естественном порядке (по возрастанию элементов). Если нужно изменить порядок сортировки элементов, то нужно реализовать стандартный функциональный интерфейс Comparator<T> и передать лямбда-выражение в данный метод. Это конечная операция.
13. Создать массив из элементов в вызывающем потоке данных
Object[] toArray()
Метод toArray() используется для преобразования потока данных в массив типа Object[]. Метод позволяет оперировать любыми типами (Integer, Double, Float и т.д.).
⇑
Связанные темы
- Обобщения. Параметризованные типы. Обобщенные классы интерфейсы, методы
- Лямбда-выражения. Основные понятия. Функциональный интерфейс. Примеры
- Стандартные (предопределенные) функциональные интерфейсы Java
- Понятие конечной и промежуточной операции. Примеры. Отличия. Методы создания потока данных stream(), parallelStream()
⇑