Spec-Zone .ru
спецификации, руководства, описания, API
|
public interface Spliterator<T>
Collection
, канал IO, или функция генератора. Spliterator может пересечь элементы индивидуально (tryAdvance()
) или последовательно оптом (forEachRemaining()
).
Spliterator может также отгородить перегородкой некоторые из своих элементов (использование trySplit()
) как другой Spliterator, чтобы использоваться в возможно параллельных операциях. Операции используя Spliterator, который не может разделить, или делает так в чрезвычайно imbalanced или неэффективный способ, вряд ли извлекут выгоду из параллелизма. Обход и разделение исчерпывают элементы; каждый Spliterator полезен для только единственного объемного вычисления.
Spliterator также сообщает о ряде characteristics()
из его структуры, источника, и элементов из числа ORDERED
, DISTINCT
, SORTED
, SIZED
, NONNULL
, IMMUTABLE
, CONCURRENT
, и SUBSIZED
. Они могут использоваться клиентами Spliterator, чтобы управлять, специализировать или упростить вычисление. Например, Spliterator для a Collection
сообщил бы SIZED
, Spliterator для a Set
сообщил бы DISTINCT
, и Spliterator для a SortedSet
также сообщил бы SORTED
. О характеристиках сообщают как простой unioned набор битов. Некоторые характеристики дополнительно ограничивают поведение метода; например, если ORDERED
, методы обхода должны соответствовать их задокументированному упорядочиванию. Новые характеристики могут быть определены в будущем, таким образом, конструкторы не должны присвоить значения не включенным в список значениям.
Spliterator, который не сообщает IMMUTABLE
или CONCURRENT
как ожидают, будет иметь задокументированное касающее политики: когда spliterator связывает с источником элемента; и обнаружение структурной интерференции источника элемента, обнаруженного после привязки. Создается позднее связывание, которое Spliterator связывает с источником элементов в точке первого обхода, сначала разделение, или сначала запрашивает для предполагаемого размера, а не в это время Spliterator. Spliterator, который не является поздним связыванием, связывает с источником элементов в точке конструкции или первом вызове любого метода. Модификации, сделанные к источнику до привязки, отражаются, когда Spliterator пересекается. После привязки Spliterator, на основе максимальных усилий, должен бросить ConcurrentModificationException
если структурная интерференция обнаруживается. Spliterators, которые делают это, вызывают сбоем быстро.
Spliterators может обеспечить оценку числа остающихся элементов через estimateSize()
метод. Идеально, как отражено в характеристике SIZED
, это значение соответствует точно числу элементов, с которым встретились бы в успешном обходе. Однако, даже когда не точно известный, значение ориентировочной стоимости может все еще быть полезным для операций, выполняемых на источнике, таких как помогание определить, предпочтительно ли разделить далее или пересечь остающиеся элементы последовательно.
Несмотря на их очевидную утилиту в параллельных алгоритмах, spliterators, как ожидают, не будут ориентированы на многопотоковое исполнение; вместо этого, реализации параллельных алгоритмов, используя spliterators должны гарантировать, что spliterator только используется одним потоком за один раз. Этого обычно легко достигнуть через последовательное ограничение потока, которое часто является естественным следствием типичных параллельных алгоритмов, которые работают рекурсивным разложением. Вызов потока trySplit()
может передать возвращенный Spliterator к другому потоку, который поочередно может пересечь или далее разделить тот Spliterator. Поведение разделения и обхода неопределено, если два или больше потока работают одновременно на том же самом spliterator. Если исходный поток передает spliterator к другому потоку для того, чтобы обработать, лучше, если это, handoff происходит перед какими-либо элементами, поглощенно tryAdvance()
, как определенные гарантии (такие как точность estimateSize()
для SIZED
spliterators), только допустимы прежде, чем обход начался.
Примитивные специализации подтипа Spliterator
предусматриваются int
, long
, и double
значения. Реализации по умолчанию подтипа tryAdvance(java.util.function.Consumer)
и forEachRemaining(java.util.function.Consumer)
поле примитивные значения к экземплярам их соответствующей обертки class. Такая упаковка может подорвать любые преимущества производительности, полученные при использовании примитивных специализаций. Чтобы избежать упаковывать, соответствующие примитивно-на основе методы должны использоваться. Например, Spliterator.OfInt.tryAdvance(java.util.function.IntConsumer)
и Spliterator.OfInt.forEachRemaining(java.util.function.IntConsumer)
должен использоваться в предпочтении к Spliterator.OfInt.tryAdvance(java.util.function.Consumer)
и Spliterator.OfInt.forEachRemaining(java.util.function.Consumer)
. Обход примитивных значений, используя основанные на упаковке методы tryAdvance()
и forEachRemaining()
не влияет на порядок, в котором встречаются со значениями, преобразованными к упакованным значениям.
Spliterators, как Iterators
s, для того, чтобы пересечь элементы источника. Spliterator
API был разработан, чтобы поддерживать эффективный параллельный обход в дополнение к последовательному обходу, поддерживая разложение так же как одноэлементную итерацию. Кроме того, протокол для того, чтобы получить доступ к элементам через Spliterator разрабатывается, чтобы наложить меньшие издержки на элемент чем Iterator
, и избегать свойственной гонки, включенной в наличие отдельных методов для hasNext()
и next()
.
Для изменчивых источников может произойти произвольное и недетерминированное поведение, если источник структурно вмешивается с (добавленные элементы, замененный, или удалил) между временем, когда Spliterator связывает с его источником данных и концом обхода. Например, такая интерференция приведет к произвольным, недетерминированным результатам при использовании java.util.stream
платформа.
Структурной интерференцией источника можно управлять следующими способами (в приблизительном порядке уменьшающейся желательности):
CopyOnWriteArrayList
неизменный источник. Spliterator, создаваемый из источника, сообщает о характеристике IMMUTABLE
.ConcurrentHashMap
параллельный источник. Spliterator, создаваемый из источника, сообщает о характеристике CONCURRENT
.ConcurrentModificationException
. Например, ArrayList
, и многие другое непараллельное Collection
классы в JDK, обеспечьте позднее связывание, приведите spliterator к сбою быстро.Пример. Вот class (не очень полезный, за исключением иллюстрации), который поддерживает массив, в котором фактические данные сдерживаются даже расположения, и несвязанные данные тега сохранены в нечетных расположениях. Его Spliterator игнорирует теги.
class TaggedArray<T> {
private final Object[] elements; // immutable after construction
TaggedArray(T[] data, Object[] tags) {
int size = data.length;
if (tags.length != size) throw new IllegalArgumentException();
this.elements = new Object[2 * size];
for (int i = 0, j = 0; i < size; ++i) {
elements[j++] = data[i];
elements[j++] = tags[i];
}
}
public Spliterator<T> spliterator() {
return new TaggedArraySpliterator<>(elements, 0, elements.length);
}
static class TaggedArraySpliterator<T> implements Spliterator<T> {
private final Object[] array;
private int origin; // current index, advanced on split or traversal
private final int fence; // one past the greatest index
TaggedArraySpliterator(Object[] array, int origin, int fence) {
this.array = array; this.origin = origin; this.fence = fence;
}
public void forEachRemaining(Consumer<? super T> action) {
for (; origin < fence; origin += 2)
action.accept((T) array[origin]);
}
public boolean tryAdvance(Consumer<? super T> action) {
if (origin < fence) {
action.accept((T) array[origin]);
origin += 2;
return true;
}
else // cannot advance
return false;
}
public Spliterator<T> trySplit() {
int lo = origin; // divide range in half
int mid = ((lo + fence) >>> 1) & ~1; // force midpoint to be even
if (lo < mid) { // split out left half
origin = mid; // reset this Spliterator's origin
return new TaggedArraySpliterator<>(array, lo, mid);
}
else // too small to split
return null;
}
public long estimateSize() {
return (long)((fence - origin) / 2);
}
public int characteristics() {
return ORDERED | SIZED | IMMUTABLE | SUBSIZED;
}
}
}
Как пример, как параллельная платформа вычисления, такой как java.util.stream
пакет, использовал бы Spliterator в параллельном вычислении, вот один способ реализовать связанную параллель forEach, который иллюстрирует основную идиому использования откола подзадач, пока предполагаемый объем работы не является достаточно небольшим, чтобы выполнить последовательно. Здесь мы предполагаем, что порядок обработки через подзадачи не имеет значения; различные (разветвленные) задачи могут далее разделить и обработать элементы одновременно в неопределенном порядке. Этот пример использует a CountedCompleter
; подобные использования применяются к другим параллельным конструкциям задачи.
static <T> void parEach(TaggedArray<T> a, Consumer<T> action) {
Spliterator<T> s = a.spliterator();
long targetBatchSize = s.estimateSize() / (ForkJoinPool.getCommonPoolParallelism() * 8);
new ParEach(null, s, action, targetBatchSize).invoke();
}
static class ParEach<T> extends CountedCompleter<Void> {
final Spliterator<T> spliterator;
final Consumer<T> action;
final long targetBatchSize;
ParEach(ParEach<T> parent, Spliterator<T> spliterator,
Consumer<T> action, long targetBatchSize) {
super(parent);
this.spliterator = spliterator; this.action = action;
this.targetBatchSize = targetBatchSize;
}
public void compute() {
Spliterator<T> sub;
while (spliterator.estimateSize() > targetBatchSize &&
(sub = spliterator.trySplit()) != null) {
addToPendingCount(1);
new ParEach<>(this, sub, action, targetBatchSize).fork();
}
spliterator.forEachRemaining(action);
propagateCompletion();
}
}
org.openjdk.java.util.stream.tripwire
устанавливается в true
тогда о диагностических предупреждениях сообщают, если упаковка примитивных значений происходит, работая на примитивных специализациях подтипа.Collection
Модификатор и Тип | Интерфейс и Описание |
---|---|
static interface |
Spliterator. OfDouble
Spliterator, специализированный для
double значения. |
static interface |
Spliterator. OfInt
Spliterator, специализированный для
int значения. |
static interface |
Spliterator. OfLong
Spliterator, специализированный для
long значения. |
Модификатор и Тип | Поле и Описание |
---|---|
static int |
ПАРАЛЛЕЛЬНЫЙ
Характеристическое значение, показывающее, что источник элемента может быть безопасно одновременно изменен (разрешение дополнений, замен, и/или удалений) многократными потоками без внешней синхронизации.
|
static int |
ОТЛИЧНЫЙ
Характеристическое значение, показывающее, что, для каждой пары элементов, с которыми встречаются,
x, y , !x.equals(y) . |
static int |
НЕИЗМЕННЫЙ
Характеристическое значение, показывающее, что источник элемента не может быть структурно изменен; то есть, элементы не могут быть добавлены, заменены, или удалены, таким образом, такие изменения не могут произойти во время обхода.
|
static int |
НЕНУЛЬ
Характеристическое значение, показывающее, что источник гарантирует, что элементы, с которыми встречаются, не будут
null . |
static int |
УПОРЯДОЧЕННЫЙ
Характеристическое значение, показывающее, что встретиться порядок определяется для элементов.
|
static int |
РАЗМЕРНЫЙ
Характеристическое значение, показывающее, что значение, возвращенное из
estimateSize() до обхода или разделения представляет конечный размер, который, в отсутствие структурной исходной модификации, представляет точное количество числа элементов, с которым встретился бы полный обход. |
static int |
СОРТИРОВАННЫЙ
Характеристическое значение, имеющее значение, которые встречаются с порядком, следует за определенным порядком сортировки.
|
static int |
ПОДРАЗМЕРНЫЙ
|
Модификатор и Тип | Метод и Описание |
---|---|
int |
characteristics()
Возвраты ряд характеристик этого Spliterator и его элементов.
|
long |
estimateSize()
Возвращает оценку числа элементов, с которым встретился бы a
forEachRemaining(java.util.function.Consumer<? super T>) обход, или возвраты Long.MAX_VALUE если большое количество, неизвестный, или слишком дорогой, чтобы вычислить. |
default void |
forEachRemaining(Consumer<? super T> action)
Выполняет данное действие для каждого остающегося элемента, последовательно в текущем потоке, пока все элементы не были обработаны, или действие выдает исключение.
|
default Comparator<? super T> |
getComparator()
|
default long |
getExactSizeIfKnown()
|
default boolean |
hasCharacteristics(int characteristics)
Возвраты
true если этот Сплитерэтор characteristics() содержите все данные характеристики. |
boolean |
tryAdvance(Consumer<? super T> action)
Если остающийся элемент существует, выполняет данное действие на этом, возвращаясь
true ; еще возвраты false . |
Spliterator<T> |
trySplit()
Если этот spliterator может быть разделен, возвращает Spliterator, покрывающий элементы, которые будут по возврату из этого метода, не покрываются этим Spliterator.
|
static final int ORDERED
trySplit()
разделяет строгий префикс элементов, того метода tryAdvance(java.util.function.Consumer<? super T>)
шаги одним элементом в префиксном порядке, и этом forEachRemaining(java.util.function.Consumer<? super T>)
выполняет действия в, встречаются с порядком. A Collection
имеет встретиться порядок если соответствие Collection.iterator()
документирует порядок. Если так, встретиться порядок является тем же самым как задокументированным порядком. Иначе, у набора нет встретиться порядка.
List
. Но никакой порядок не гарантируется для основанных на хеше наборов такой как HashSet
. Клиенты Spliterator, который сообщает ORDERED
как ожидают, сохранят ограничения упорядочивания в некоммутативных параллельных вычислениях.static final int DISTINCT
x, y
, !x.equals(y)
. Это применяется например к Spliterator, основанному на a Set
.static final int SORTED
getComparator()
возвращает связанный Компаратор, или null
если все элементы Comparable
и сортируются их естественным упорядочиванием. Spliterator, который сообщает SORTED
должен также сообщить ORDERED
.
Collection
классы в JDK та реализация NavigableSet
или SortedSet
отчет SORTED
.static final int SIZED
estimateSize()
до обхода или разделения представляет конечный размер, который, в отсутствие структурной исходной модификации, представляет точное количество числа элементов, с которым встретился бы полный обход.Collection
сообщите об этой характеристике. Sub-spliterators, такой как те для HashSet
, то покрытие подмножество элементов и приблизительный их размер, о котором сообщают, не делает.static final int NONNULL
null
. (Это применяется, например, к большинству параллельных наборов, очередей, и карт.)static final int IMMUTABLE
IMMUTABLE
или CONCURRENT
как ожидают, будет иметь задокументированную политику (например бросок ConcurrentModificationException
) относительно структурной интерференции, обнаруженной во время обхода.static final int CONCURRENT
Верхний уровень Spliterator не должен сообщить CONCURRENT
и SIZED
, так как конечный размер, если известный, может измениться, если источник одновременно изменяется во время обхода. Такой Spliterator непоследователен, и никакие гарантии не могут быть сделаны ни о каком вычислении, используя тот Spliterator. Sub-spliterators может сообщить SIZED
если размер подразделения известен и дополнения, или удаления к источнику не отражаются, пересекая.
static final int SUBSIZED
trySplit()
будут оба SIZED
и SUBSIZED
. (Это означает, что весь дочерний элемент Сплитерэторс, или прямой или косвенный, будет SIZED
.) Spliterator, который не сообщает SIZED
как требуется SUBSIZED
непоследовательно, и никакие гарантии не могут быть сделаны ни о каком вычислении, используя тот Spliterator.
SIZED
но нет SUBSIZED
, так как распространено знать размер всего дерева, но не точные размеры поддеревьев.boolean tryAdvance(Consumer<? super T> action)
true
; еще возвраты false
. Если этот Spliterator ORDERED
действие выполняется на следующем элементе в, встречаются с порядком. Исключения, выданные действием, передаются к вызывающей стороне.action
- Действиеfalse
если никакие остающиеся элементы не существовали после записи в этот метод, еще true
.NullPointerException
- если указанное действие является нулемdefault void forEachRemaining(Consumer<? super T> action)
ORDERED
, действия выполняются в, встречаются с порядком. Исключения, выданные действием, передаются к вызывающей стороне.tryAdvance(java.util.function.Consumer<? super T>)
пока это не возвращается false
. Это должно быть переопределено когда бы ни было возможно.action
- ДействиеNullPointerException
- если указанное действие является нулемSpliterator<T> trySplit()
Если этот Spliterator ORDERED
, возвращенный Spliterator должен покрыть строгий префикс элементов.
Если этот Spliterator не покрывает бесконечное число элементов, повторенных звонков trySplit()
должен в конечном счете возвратиться null
. По ненулевому возврату:
estimateSize()
перед разделением, если не уже нуль или Long.MAX_VALUE
, после разделения, должно быть больше чем estimateSize()
для этого и возвращенного Spliterator; иSUBSIZED
, тогда estimateSize()
для этого spliterator прежде, чем разделение должно быть равным сумме estimateSize()
для этого и возвращенного Spliterator после разделения.Этот метод может возвратиться null
по любой причине, включая пустоту, неспособность разделить после того, как обход начался, ограничения структуры данных, и соображения эффективности.
trySplit
метод эффективно (без обхода) делит свои элементы точно на половину, позволяя сбалансированное параллельное вычисление. Много отклонений от этого идеала остаются очень эффективными; например, только приблизительно разделяя приблизительно сбалансированное дерево, или для дерева, в котором вершины могут содержать или один или два элемента, будучи не в состоянии далее разделить эти узлы. Однако, большие отклонения в балансе и/или чрезмерно неэффективный trySplit
механика обычно приводит к плохой параллельной производительности.Spliterator
покрытие некоторой части элементов, или null
если этот spliterator не может быть разделенlong estimateSize()
forEachRemaining(java.util.function.Consumer<? super T>)
обход, или возвраты Long.MAX_VALUE
если большое количество, неизвестный, или слишком дорогой, чтобы вычислить. Если этот Spliterator SIZED
и еще не был частично пересечен или разделен, или этот Spliterator SUBSIZED
и еще не был частично пересечен, эта оценка должна быть точным количеством элементов, с которыми встретился бы полный обход. Иначе, эта оценка может быть произвольно неточной, но должна уменьшиться как определено через вызовы trySplit()
.
Long.MAX_VALUE
если большое количество, неизвестный, или слишком дорогой, чтобы вычислить.default long getExactSizeIfKnown()
estimateSize()
если Spliterator сообщает о характеристике SIZED
, и -1
иначе.-1
.int characteristics()
ORDERED
, DISTINCT
, SORTED
, SIZED
, NONNULL
, IMMUTABLE
, CONCURRENT
, SUBSIZED
. Повторные звонки characteristics()
на данном spliterator должен всегда возвращать тот же самый результат. Если Spliterator сообщает о непоследовательном наборе характеристик (или возвращенные из единственного вызова или через многократные вызовы), никакие гарантии не могут быть сделаны ни о каком вычислении, используя этот Spliterator.
default boolean hasCharacteristics(int characteristics)
true
если этот Сплитерэтор characteristics()
содержите все данные характеристики.true
если все указанные характеристики присутствуют, еще false
default Comparator<? super T> getComparator()
SORTED
a Comparator
, возвраты это Comparator
. Если источник SORTED
в естественном порядке, возвратах null
. Иначе, если источник не SORTED
, броски IllegalStateException
.IllegalStateException
.null
если элементы сортируются в естественном порядке.IllegalStateException
- если spliterator не сообщает о характеристике SORTED
.
Для дальнейшей ссылки API и документации разработчика, см. Java Документация SE. Та документация содержит более подробные, предназначенные разработчиком описания, с концептуальными краткими обзорами, определениями сроков, обходных решений, и рабочих примеров кода.
Авторское право © 1993, 2013, Oracle и/или его филиалы. Все права защищены.
Проект сборка-b92