Java. Потоки данных. Stream API. Общая информация




Потоки данных. Stream API. Общая информация

Перед изучением данной темы рекомендуется ознакомиться со следующими темами:


Содержание


Поиск на других ресурсах:

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 и т.д.).

 


Связанные темы