T
- 此Spliter的返回元素的类型
public interface Spliterator<T>
Collection
,IO通道或生成器函数。
分割器可以逐个遍历元素( tryAdvance()
)或批量( forEachRemaining()
)。
分割器也可以将其某些元素(使用trySplit()
) 分割为另一个分割器,以在可能的并行操作中使用。 使用不能分割的Spliter的操作或者以非常不平衡或低效的方式进行的操作不太可能受益于并行性。 穿透和分流排气元件; 每个Spliterator仅对单个批量计算有用。
甲Spliterator还报告一组characteristics()
选自其结构,源极和元件的ORDERED
, DISTINCT
, SORTED
, SIZED
, NONNULL
, IMMUTABLE
, CONCURRENT
和SUBSIZED
。 这些可以由Spliterator客户端使用来控制,专门化或简化计算。 例如,Collection
的Spliterator将报告SIZED
,一个用于Set
的Spliterator将报告DISTINCT
,一个用于SortedSet
的Spliterator也将报告SORTED
。 特性报告为简单的单位位。 一些特征还限制了方法行为; 例如,如果ORDERED
,遍历方法必须符合其记录的顺序。 未来可能会定义新特性,因此实现者不应将含义分配给未列出的值。
A Spliterator that does not report IMMUTABLE
or CONCURRENT
is expected to have a documented policy concerning: when the spliterator binds to the element source; and detection of structural interference of the element source detected after binding. 后期绑定的 Spliterator在第一次遍历,第一次拆分或第一个查询时针对估计大小而不是在创建Spliter时绑定到元素的来源。 没有晚期绑定的拼接器在构造或首次调用任何方法时绑定到元素的来源。 在绑定之前对源进行的修改在Spliter运行时被反映。 绑定后,如果检测到结构性干扰,拼图器应尽可能地抛出ConcurrentModificationException
。 这样做的分割器称为故障快速 。 Spliter的批量遍历方法( forEachRemaining()
)可以优化遍历并检查所有元素已经遍历之后的结构干扰,而不是立即检查每个元素并失败。
分配器可以通过estimateSize()
方法提供剩余元素数量的估计。 理想情况下,如特征SIZED
中所反映的那样 ,该值完全对应于成功遍历时遇到的元素的数量。 然而,即使不是完全知道的,估计的值值对于在源上执行的操作仍然有用,例如有助于确定是否优选进一步分割或者顺序地遍历剩余的元素。
尽管它们在并行算法中具有明显的实用性,但拼接器并不期望是线程安全的; 相反,使用分割器的并行算法的实现应该确保分割器一次只被一个线程使用。 这通常是通过串行线程限制来获得的,这通常是通过递归分解工作的典型并行算法的自然结果。 调用trySplit()
的线程可能会将返回的Spliterator移交给另一个线程,而该线程又可以遍历或进一步拆分该分割器。 如果两个或多个线程在同一个分割器上同时运行,则分割和遍历的行为是未定义的。 如果原来的线程将一个分线器关闭到另一个线程进行处理,则最好是在任何元素消耗tryAdvance()
之前发生切换,因为某些保证(例如SIZED分频器的SIZED
精度)仅在遍历开始之前有效。
的原始亚型特Spliterator
被提供用于int
, long
和double
值。 子类型默认实现tryAdvance(java.util.function.Consumer)
和forEachRemaining(java.util.function.Consumer)
框原始值到其对应的包装器类的实例。 这种拳击可能会破坏使用原始专长所获得的任何性能优势。 为了避免拳击,应该使用相应的基于图元的方法。 例如, 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()
对原始值的遍历不会影响遇到转换为框值的值的顺序。
分流器,如Iterators
s,用于遍历源的元素。 Spliterator
API旨在通过支持分解和单元素迭代来支持除顺序遍历之外的高效并行遍历。 此外,用于通过Spliterator访问元素的协议被设计为比Iterator
施加更小的每元素开销,并且避免为hasNext()
和next()
分开方法所涉及的固有竞争。
对于可变源,如果在Striterator绑定到其数据源的时间与遍历结束之间,源在结构上受到干扰(添加,替换或删除的元素),则可能会发生任意和非确定性行为。 例如,当使用java.util.stream
框架时,这种干扰将产生任意的非确定性结果。
源的结构干扰可以通过以下方式进行管理(大概顺序为减少的可取性):
CopyOnWriteArrayList
的一个实例是一个不可变的来源。 从源头创建的Spliterator报告了IMMUTABLE的IMMUTABLE
。 ConcurrentHashMap
的密钥集是并发源。 从源头创建的Spliterator报告了CONCURRENT的CONCURRENT
。 ConcurrentModificationException
。 例如, ArrayList
和JDK中的许多其他非并发的Collection
类,提供了后期绑定,故障快速分片器。 ConcurrentModificationException
因为潜在的干扰窗口较大。 例。 这是一个类(不是非常有用的,除了说明),它维护一个数组,其中实际数据保存在偶数位置,而不相关的标签数据保存在奇数位置。 它的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的一种方法,它说明了拆分子任务的主要用法,直到估计工作量足够小以顺序执行。 这里我们假设子任务处理的顺序并不重要; 不同的(分叉)任务可以进一步拆分并以未确定的顺序处理元素。 本例使用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
Modifier and Type | Interface and Description |
---|---|
static interface |
Spliterator.OfDouble
A Spliterator专门为
double 值。
|
static interface |
Spliterator.OfInt
A Spliterator专门为
int 值。
|
static interface |
Spliterator.OfLong
A Spliterator专门为
long 值。
|
static interface |
Spliterator.OfPrimitive<T,T_CONS,T_SPLITR extends Spliterator.OfPrimitive<T,T_CONS,T_SPLITR>>
专门针对原始价值观的Spliterator。
|
Modifier and Type | Field and Description |
---|---|
static int |
CONCURRENT
特征值表示可以通过多个线程安全同时修改元素源(允许添加,替换和/或删除),而无需外部同步。
|
static int |
DISTINCT
特性值这标志着,对于每对遇到的元件
x, y ,
!x.equals(y) 。
|
static int |
IMMUTABLE
特征值表示元素源不能在结构上进行修改;
也就是说,不能添加,替换或删除元素,因此在遍历过程中不会发生这种更改。
|
static int |
NONNULL
特征值表示源保证遇到的元素不会为
null 。
|
static int |
ORDERED
特征值表示为元素定义遇到顺序。
|
static int |
SIZED
表示在遍历或
estimateSize() 之前从
estimateSize() 返回的值的特征值表示在没有结构源修改的情况下表示完全遍历将遇到的元素数量的精确计数的有限大小。
|
static int |
SORTED
特征值表示遇到的顺序遵循定义的排序顺序。
|
static int |
SUBSIZED
|
Modifier and Type | Method and Description |
---|---|
int |
characteristics()
返回此Spliterator及其元素的一组特征。
|
long |
estimateSize()
返回
forEachRemaining(java.util.function.Consumer<? super T>) 遍历将遇到的元素数量的估计,如果无穷大,未知数或计算
成本太高,则返回
Long.MAX_VALUE 。
|
default void |
forEachRemaining(Consumer<? super T> action)
在当前线程中依次执行每个剩余元素的给定操作,直到所有元素都被处理或动作引发异常。
|
default Comparator<? super T> |
getComparator()
如果这个Spliterator的来源是 SORTED 由Comparator ,返回Comparator 。
|
default long |
getExactSizeIfKnown()
|
default boolean |
hasCharacteristics(int characteristics)
返回
true 如果Spliterator的
characteristics() 包含所有给定的特性。
|
boolean |
tryAdvance(Consumer<? super T> action)
如果剩下的元素存在,执行给定的操作,返回 true ;
否则返回false 。
|
Spliterator<T> |
trySplit()
如果此分割器可以被分区,返回一个包含元素的Spliter,当从该方法返回时,它不会被该Spliter所覆盖。
|
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
没有保证任何顺序。
报告ORDERED
客户端将预期在非交换并行计算中保留排序约束。
static final int DISTINCT
x, y
, !x.equals(y)
。
这适用于例如基于Set
的Spliterator 。
static final int SORTED
getComparator()
返回相关的比较器,或null
如果所有元素都是Comparable
,并按其自然排序进行排序。
报告SORTED
也必须报ORDERED
。
Collection
类的编译器实现NavigableSet
或SortedSet
报告SORTED
。
static final int SIZED
estimateSize()
之前从
estimateSize()
返回的值的特征值表示在没有结构源修改的情况下表示完全遍历将遇到的元素数量的精确计数的有限大小。
Collection
报告这一特点。
子分割器,例如HashSet
的子分割器 ,不包括覆盖元素的子集并且近似其报告的大小。
static final int NONNULL
null
。
(这适用于大多数并发集合,队列和映射)。
static final int IMMUTABLE
IMMUTABLE
或CONCURRENT
预计将有关于在遍历期间检测到的结构性干扰的文件化策略(例如投掷ConcurrentModificationException
)。
static final int CONCURRENT
顶级Spliterator不应同时报告CONCURRENT
和SIZED
,因为如果已知的有限大小可能会在遍历期间同时修改源时发生更改。 这样的分割器是不一致的,并且不能保证使用该分割器的任何计算。 子分割器可以报告SIZED
如果子分割大小是已知的,并且在遍历时不反映源的添加或移除。
static final int SUBSIZED
trySplit()
将是既SIZED
和SUBSIZED
。
(这意味着无论是直接还是间接的,所有的小孩拼写器都将是SIZED
)
根据SUBSIZED的要求不会报告SIZED
的SUBSIZED
不一致,并且不能保证使用该Spliter的任何计算。
SIZED
而不是
SUBSIZED
,因为通常知道整个树的大小,而不知道子树的确切大小。
boolean tryAdvance(Consumer<? super T> action)
true
;
否则返回false
。
如果此Spliterator是ORDERED
,则会在遇到的顺序的下一个元素上执行该操作。
动作抛出的异常被转发给呼叫者。
action
- 行动
false
如果在进入该方法时没有剩余元素,否则
true
。
NullPointerException
- 如果指定的动作为空
default void forEachRemaining(Consumer<? super T> action)
tryAdvance(java.util.function.Consumer<? super T>)
,直到它返回false
。
应尽可能覆盖。
action
- 行动
NullPointerException
- 如果指定的动作为空
Spliterator<T> trySplit()
如果此Spliterator为ORDERED
,则返回的Spliterator必须覆盖元素的严格前缀。
除非这个Spliterator包含无数个元素,否则重复调用trySplit()
必须最终返回null
。 非空返回:
estimateSize()
分割之前,必须分割后,大于或等于estimateSize()
,这和返回Spliterator; 和 SUBSIZED
,然后estimateSize()
这个spliterator分裂之前必须等于总和estimateSize()
,这和拆分后返回Spliterator。 该方法可能由于任何原因返回null
,包括空虚,遍历开始后无法拆分,数据结构约束和效率考虑。
trySplit
方法有效(无遍历)将其元素精确地分成两半,允许平衡的并行计算。
许多离开这个理想的人仍然是非常有效的;
例如,仅近似分裂近似平衡的树,或者对于叶节点可以包含一个或两个元素的树,不能进一步分割这些节点。
然而,平衡和/或过低trySplit
大偏差trySplit
机械通常导致较差的并行性能。
Spliterator
覆盖部分元素,或
null
如果此拼接器无法拆分
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之前或在两者之间的调用, trySplit
,应始终返回相同的结果。
如果Spliterator报告不一致的特征集(从单个调用返回的或多个调用返回的),则不能保证使用此Spliter的任何计算。
SIZED
, SUBSIZED
和CONCURRENT
。
default boolean hasCharacteristics(int characteristics)
true
如果Spliterator的
characteristics()
包含所有给定的特性。
characteristics
- 检查的特点
true
如果所有指定的特性都存在,否则
false
default Comparator<? super T> getComparator()
SORTED
由Comparator
,返回Comparator
。
如果来源是SORTED
在natural order ,返回null
。
否则,如果源不是SORTED
,则抛出IllegalStateException
。
IllegalStateException
。
null
如果元素按照自然顺序排序。
IllegalStateException
- 如果拼接器没有报告SORTED的
SORTED
。