Статьи

Использование Spliterator в Java

Вступление:

Итераторы в Java используются для прохождения элементов данного источника. Spliterator в Java является одним из четырех доступных итераторов Java — Iterator, Enumeration, ListIterator и Spliterator . Это интерфейс, доступный в пакете java.util .

Spliterator был впервые представлен в Java 8 для поддержки параллельного программирования. Однако мы можем использовать его как для последовательной, так и для параллельной обработки элементов данных. Чтобы получить экземпляр Java Spliterator , мы будем использовать метод spliterator () :

1
2
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Spliterator splitr = list.spliterator();

Мы можем думать о Java Spliterator как:

1
Spliterator = Splitting + Iteration

Характеристики сплитератора :

Интерфейс Spliterator определяет некоторые интегральные константы, представляющие его характеристики. Наш экземпляр может иметь одну или несколько из следующих восьми характеристик:

  • SIZED — способен возвращать точное количество элементов в источнике, когда мы вызываем метод valuSize ()
  • SUBSIZED — когда мы разделяем экземпляр с помощью trySplit () и получаем также SIZED SplitIterators
  • ORDERED — перебор упорядоченной последовательности
  • SORTED — перебирать отсортированную последовательность
  • NONNULL — источник гарантирует, что значения не равны NULL
  • DISTINCT — в нашей исходной последовательности нет дубликатов
  • IMMUTABLE — если мы не можем структурно изменить источник элемента
  • CONCURRENT — источник элемента может быть безопасно одновременно изменен

Мы можем использовать метод int Характеристики () для запроса характеристик нашего экземпляра Spliterator . Он возвращает значение OR для всех значений квалифицирующих признаков для нашего Spliterator . Для нашего определенного разделителя у нас будет:

1
int charactersticsORed = splitr.characteristics(); //16464

hasCharacteristics () :

Мы можем использовать логический метод hasCharacteristics (int признак), чтобы проверить, имеет ли наш экземпляр данную характеристику или нет:

1
2
3
boolean isSized = splitr.hasCharacteristics(Spliterator.SIZED);   //true
boolean isSorted = splitr.hasCharacteristics(Spliterator.SORTED); //false
boolean isNonNull = splitr.hasCharacteristics(Spliterator.NONNULL); //false

estimateSize ():

МетодtimateSize () возвращает приблизительное количество элементов, оставшихся для итерации. Он возвращает Long.MAX_VALUE, если значение бесконечно, неизвестно или слишком дорого для вычисления. Для SIZED Spliterator он возвращает значение, которое точно соответствует количеству элементов, которые будут встречаться при успешном обходе:

1
long estimatedSize = splitr.estimateSize(); // 5

getExactSizeIfKnown ():

Это просто вспомогательный метод, который возвращает оценкуSize (), если это SIZED Spliterator или возвращает -1 :

1
long size = splitr.getExactSizeIfKnown(); // 5

tryAdvance ():

Подпись метода tryAdvance () выглядит следующим образом:

1
default boolean tryAdvance(Consumer<? super T> action)

Метод tryAdvance () в Spliterator объединяет операторы hasNext () и next (), присутствующие в базовом итераторе . Поэтому, если остающийся элемент существует, он выполняет с ним заданное действие, возвращая true; иначе возвращает ложь . Другими словами, он выполняет действие над следующим элементом в последовательности, а затем продвигает итератор.

1
while(splitr.tryAdvance((item) -> System.out.println(item)));

Если у нас есть ORDERED Spliterator , действие выполняется над следующим элементом в порядке столкновения.

forEachRemaining ():

Метод forEachRemaining (Consumer <? SuperT> action) выполняет данное действие для каждого оставшегося элемента, последовательно в текущем потоке, пока все элементы не будут обработаны или действие не вызовет исключение:

1
splitr.forEachRemaining(item -> System.out.println(item));

Текущая реализация по умолчанию неоднократно вызывает tryAdvance (), пока не вернет false .

trySplit ():

Если разбиение возможно, метод trySplit () разделяет вызывающий Spliterator и возвращает ссылку на элементы покрытия Spliterator, которые не будут покрываться этим Spliterator по возвращении из этого метода. В противном случае возвращается ноль .

Таким образом, после успешного разделения оригинальный Spliterator будет выполнять итерацию по одной части последовательности, а возвращенный Spliterator — по другой ее части.

Кроме того, возвращаемый Spliterator охватывает строгий префикс элементов для начального ORDERED Spliterator (например, над списком ) :

01
02
03
04
05
06
07
08
09
10
// trySplit() method over ORDERED splitr
Spliterator<Integer> splitrNew = splitr.trySplit();
           
// Elements in our splitrNew = {1, 2, 3}
if(splitrNew != null) {
    splitrNew.forEachRemaining((n) -> System.out.println(n));
}
   
// Elements in our splitr - {4 , 5}
splitr.forEachRemaining((n) -> System.out.println(n));

Если только наш оригинальный Spliterator не представляет бесконечную последовательность, повторные вызовы trySplit () должны в конечном итоге вернуть null .

getComparator () :

Если у нас есть Spliterator, отсортированный компаратором , он возвращает этот компаратор . Или же он возвращает ноль, если источник отсортирован в естественном порядке. Для источника, который не отсортирован , он выдаст исключение IllegalStateException .

Итак, для нашего примера мы имеем:

1
Comparator<Integer> comparator = splitr.getComparator(); //throws IllegalStateException

Зачем использовать Spliterator?

Java Spliterator предлагает нам несколько преимуществ:

  • Поддерживает параллельное программирование
  • Мы можем использовать его как для последовательной, так и для параллельной обработки элементов данных.
  • Метод tryAdvance () объединяет операции next () и hasNext () простого итератора и, таким образом, обеспечивает более высокую производительность.

Также важно понимать, что Spliterator отлично работает как для источников Collection, так и для потоков , но не с реализациями Map в качестве источника.

Вывод:

В этой статье мы познакомили вас с интерфейсом Spliterator в Java. Мы рассмотрели различные методы по умолчанию, доступные в этом интерфейсе, и способы их использования.

Оставьте первый комментарий.

Опубликовано на Java Code Geeks с разрешения Шубхры Шриваставы, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Использование Spliterator в Java

Мнения, высказанные участниками Java Code Geeks, являются их собственными.