java8 Spliterator接口API翻译

来源:互联网 发布:华信软件学院 编辑:程序博客网 时间:2024/06/07 22:46
java.util

Interface Spliterator<T>

  • 类型参数:
       T -此Spliterator的返回元素的类型
    所有已知子接口:
           Spliterator.OfDouble, Spliterator.OfInt, Spliterator.OfLong, Spliterator.OfPrimitive<T,T_CONS,T_SPLITR>
    所有已知实现类:
    Spliterators.AbstractDoubleSpliterator, Spliterators.AbstractIntSpliterator, Spliterators.AbstractLongSpliterator,Spliterators.AbstractSpliterator
public interface Spliterator<T>
用于遍历和分割源的元素的对象。 由Spliterator覆盖的元素的来源可以是例如数组,集合,IO通道或生成函数(generator function)。
分割器可以单独遍历元素(tryAdvance())或以批量方式(forEachRemaining())顺序遍历。

分割器也可以将其一些元素(使用trySplit())分割为另一个Spliterator,以便在可能的并行操作中使用。 使用不能分割的Spliterator的操作或者以非常不平衡或低效的方式进行的操作不太可能受益于并行性。 遍历和分割分区数据; 每个Spliterator仅对单个批量计算有用。

Spliterator还从ORDERED,DISTINCT,SORTED,SIZED,NONNULL,IMMUTABLE,CONCURRENT和SUBSIZED中报告其结构,源和元素的一组characteristics()。 这些可以由Spliterator客户端使用来控制,专门化或简化计算。 例如,集合的Spliterator将报告SIZED,集合的Spliterator将报告DISTINCT,并且SortedSet的Spliterator也将报告SORTED。 特性报告为简单的联合位集合。 一些特征还限制了方法行为; 例如,如果ORDERED,遍历方法必须符合其记录的顺序。 未来可能会定义新特性,因此实现者不应将含义分配给未列出的值。

不报告IMMUTABLE或CONCURRENT的Spliterator预计将有一个有关的文件化策略:当Spliterator绑定到元素源时;并检测结合后检测到的元素源的结构干扰。后期绑定的Spliterator在第一次遍历,第一次拆分或第一个查询时针对估计大小而不是在创建Spliterator时绑定到元素的来源。没有晚期绑定的拼接器在构造或首次调用任何方法时绑定到元素的来源。在绑定之前对源进行的修改在Spliterator运行时被反映。绑定后,如果检测到结构性干扰,Spliterator应该尽力而为地抛出ConcurrentModificationException异常。这样做的分割器称为故障快速。 Spliterator的批量遍历方法(forEachRemaining())可以优化遍历,并在所有元素都被遍历之后检查结构干扰,而不是立即检查每个元素并失败。

分割器可以通过estimateSize()方法提供剩余元素数量的估计。 理想情况下,如特征SIZED所反映的那样,该值与完成遍历时遇到的元素的数量完全对应。 然而,即使不是完全知道的,估计的值对于在源上执行的操作仍然有用,例如有助于确定是否优选进一步分割或者顺序地遍历剩余的元素。

尽管它们在并行算法中具有明显的实用性,但spliterator并不期望是线程安全的; 相反,使用分割器(spliterator)的并行算法的实现应该确保分割器一次只被一个线程使用。 这通常是通过串行线程限制来获得的,这通常是通过递归分解工作的典型并行算法的自然结果。 调用trySplit()的线程可以将返回的Spliterator移交给另一个线程,然后可以遍历或进一步拆分该分割器。 如果两个或多个线程在同一个分割器上同时运行,则分割和遍历的行为是未定义的。 如果原始线程将一个分割器关闭到另一个线程进行处理,则最好是在使用tryAdvance()之前发生切换,因为某些保证(例如,SIZED分割器的estimateSize()的精度)只有在遍历开始之前才有效。

Spliterator的原始特定子类型由int,long和double值提供。 子类型默认实现为tryAdvance(java.util.function.Consumer)和forEachRemaining(java.util.function.Consumer)包装(box)的原始值到其对应的包装器类的实例。 这种包装可能会破坏使用特定原始类型所获得的任何性能优势。 为了避免这种包装,应该使用相应的基于图元的方法。 例如,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()不影响遇到转换为包装的值的顺序。

API 注意点:
Spliterator,类似于迭代器,用于遍历源的元素。 Spliterator API被设计为支持顺序遍历,通过支持分解以及单元素迭代来支持有效的并行遍历。 此外,通过Spliterator访问元素的协议被设计为比Iterator施加更小的单元素开销,并避免为hasNext()和next()分别使用单独的方法所涉及的内在竞争。

对于可变源,如果在Striterator绑定到其数据源的时间与遍历结束之间,源在结构上受到干扰(添加,替换或删除的元素),则可能会发生任意和非确定性行为。 例如,当使用java.util.stream框架时,这种干扰将产生任意的非确定性结果。

源的结构干扰可以通过以下方式进行管理(大概顺序为减少的可取性):
  • 来源不能在结构上受到干扰。例如,CopyOnWriteArrayList的一个实例是一个不可变的源。从源头创建的Spliterator报告了IMMUTABLE的特征。
  • 源管理并发修改。例如,ConcurrentHashMap的一个关键集是并发源。从源头创建的Spliterator报告了CONCURRENT的特征。
  • 变源提供后期绑定和快速失败分片器。后期约束使窗口缩小,在此期间干扰可影响计算;快速失败检测在尽力而为的基础上,在遍历开始后发生结构性干扰,并引发ConcurrentModificationException。例如,ArrayList和JDK中的许多其他非并发Collection类提供了后期绑定,快速失败分片器。
  • 可变源提供了一个非后期绑定但是快速失败的分片器。源可能会增加ConcurrentModificationException的可能性,因为潜在的干扰窗口较大。
  • 可变源提供后期绑定和非快速失败的分片器。由于没有检测到干扰,因此源头在穿越开始后会产生任意的非确定性行为。
  • 可变源提供非后期绑定和非快速失败的分片器。来源会增加任意非确定性行为的风险,因为在建设后可能会发生非检测到的干扰。

示例。 这是一个类(不是非常有用的,除了说明),它维护一个数组,其中实际数据保存在偶数位置,而不相关的标签数据则保存在奇数位置。 它的Spliterator忽略标签。
class TaggedArray<T>
{
    private final Object[] elements; // 构造后不可变
    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; // 当前索引,分割或遍历前进
        private final int fence; // 一个过去最大的索引
 
        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; // 将范围缩小一半
            int mid = ((lo + fence) >>> 1) & ~1; //强制中点为偶数
            if (lo < mid)   // 分出左半边
            {
                origin = mid; //重新设置此拼接器原点
                return new TaggedArraySpliterator<>(array, lo, mid);
            }
            else       // 太小不能分裂
                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,则在对原始子类型专门化进行操作时,如果出现基本值的封锁,则会报告诊断警告。
从以下版本开始:
        1.8
另请参见:
        Collection
 
    • 嵌套类摘要

      Nested Classes修饰符和类型接口和说明static interface Spliterator.OfDouble
      专门用于double值的Spliterator。
      static interface Spliterator.OfInt
      一个专门针对int值的Spliterator。
      static interface Spliterator.OfLong
      一个专门针对long值的Spliterator。
      static interface Spliterator.OfPrimitive<T,T_CONS,T_SPLITR extends Spliterator.OfPrimitive<T,T_CONS,T_SPLITR>>
      专门针对原始类型的Spliterator。
    • 方法摘要

      Fields修饰符和类型字段和描述static intCONCURRENT
      特征值表示可以通过多个线程安全同时修改元素源(允许添加,替换和/或删除),而无需外部同步。
      static intDISTINCT
      对于每对遇到的元素x,y,!x.equals(y)的特征值表示,。
      static intIMMUTABLE
      特征值表示元素源不能在结构上进行修改; 也就是说,不能添加,替换或删除元素,因此在遍历过程中不会发生这种更改。
      static intNONNULL
      特征值表示源保证遇到的元素不会为空。
      static intORDERED
      特征值表示为元素定义遇到的顺序。
      static intSIZED
      特征值表示在遍历或分割之前从estimateSize()返回的值表示有限大小,在没有结构源修改的情况下,表示完整遍历并将遇到的元素数量精确计数。
      static intSORTED
      特征值表示遇到的顺序遵循定义的排序顺序。
      static intSUBSIZED
      特征值表示由三个Split()生成的所有Spliterator都将为SIZE和SUBSIDIZED。
    • 方法摘要

      All MethodsInstance MethodsAbstract MethodsDefault Methods修饰符和类型方法和说明intcharacteristics()
      返回此Spliterator及其元素的一组特征。
      longestimateSize()
      返回一个forEachRemaining(java.util.function.Consumer <?super T>)遍历所遇到的元素得数量的估计,或者返回Long.MAX_VALUE,如果为无穷大,未知,或太大而无法计算。
      default voidforEachRemaining(Consumer<? super T> action)
      在当前线程中依次执行每个剩余元素的给定操作,直到所有元素都被处理或动作引发异常。
      default Comparator<? super T>getComparator()
      如果此Spliterators源由比较器排序(SORTED),则返回该比较器。
      default longgetExactSizeIfKnown()
      返回此Spliterator 的估计大小的便捷方法为SIZED,否则为-1。
      default booleanhasCharacteristics(int characteristics)
      如果此Spliterator的characteristics()包含所有给定的特征,则返回true。
      booleantryAdvance(Consumer<? super T> action)
      如果剩余元素存在,执行给定的操作,返回true; 否则返回false。
      Spliterator<T>trySplit()
      如果此spliterator 可以被分区,返回一个包含元素的spliterator ,当从该方法返回时,它不会被该spliterator所覆盖。
    • 字段详细

      • ORDERED

        static final int ORDERED
        特征值表示为元素定义遇到的顺序。 如果是这样的话,这个Spliterator保证方法trySplit()分割一个严格的元素前缀,该方法以前缀顺序由一个元素按顺序执行tryAdvance(java.util.function.Consumer <?super T>),该forEachRemaining(java.util。 function.Consumer <?super T>)以遇到的顺序执行动作。
        如果相应的Collection.iterator()记录了一个顺序,则Collection有一个遇到的顺序。 如果是这样,遇到的顺序与记录的顺序相同。 否则,集合没有遇到顺序。
        API注:
                  遇到的顺序保证为任何列表的升序索引顺序。 但是基于哈希的集合(如HashSet)没有保证任何顺序。 报告ORDERED的Spliterator的客户端将预期在非交换并行计算中保留排序约束。
        另请参见:
                常数值
      • DISTINCT

        static final int DISTINCT
        特征值表示,对于每对遇到的元素x,y,!x.equals(y)。 这适用于例如基于Set的Spliterator。
        另请参见:
                       常数值
      • SORTED

        static final int SORTED
        特征值表示遇到的顺序遵循定义的排序顺序。 如果是这样,方法getComparator()返回相关的比较器,如果所有元素都是可比较的,并且按其自然顺序排序,则返回null。
        报告SORTED的Spliterator也必须报告顺序。
        API注:
                    实现NavigableSet或SortedSet的JDK中的Collection类的分隔符报告为SORTED。
        另请参见:
                    常数值
      • SIZED

        static final int SIZED
        特征值表示在遍历或分割之前从estimateSize()返回的值表示有限大小,在没有结构源修改的情况下,表示完整遍历所遇到的元素数量的精确计数。
        API注:
                大多数集合的分割器,涵盖集合的所有元素报告此特征。 子分割器(例如HashSet的子分割器)覆盖了一组子元素并且近似于其报告的大小。
        另请参见:
                常数值
      • NONNULL

        static final int NONNULL
        特征值表示源保证遇到的元素不会为空。 (这适用于大多数并发集合,队列和映射)。
        另请参见:
                      常数值
      • IMMUTABLE

        static final int IMMUTABLE
        特征值表示元素源不能在结构上进行修改; 也就是说,不能添加,替换或删除元素,因此在遍历过程中不会发生这种更改。 不报告IMMUTABLE或CONCURRENT的Spliterator 预计会有一个有关在遍历期间检测到的结构性干扰的文档化策略(例如抛出ConcurrentModificationException)。
        另请参见:
                        常数值
      • CONCURRENT

        static final int CONCURRENT
        特征值表示可以通过多个线程安全同时修改元素源(允许添加,替换和/或删除),而无需外部同步。 如果是这样,则Spliterator应该有一个关于在遍历期间修改影响的文件化策略。
        顶级Spliterator不应该同时报告CONCURRENT和SIZED,因为如果已知的有限大小可能会在遍历期间同时修改源时发生更改。 这样的分割器是不一致的,并且不能保证使用该分割器的任何计算。 子分割器可能会报告SIZED是否已知子分割大小,并且在遍历时不反映源的添加或删除。
        API注:
                    大多数并发收藏集保持一致性政策,保证在Spliterator构建点存在的元素的准确性,但可能不反映随后的添加或删除。
        另请参见:
                   常数值
      • SUBSIZED

        static final int SUBSIZED
        特征值表示由trySplit()生成的所有Spliterator都将都是SIZED和SUBSIZED。 (这意味着,无论是直接还是间接的,所有子分支器都将被大小化。)
        不按照SUBSIZED的要求报告SIZED的Spliter不一致,不能保证使用该Spliter的任何计算。
        API注:
                一些拼接器,例如用于大致平衡的二叉树的顶级拼接器,将报告SIZED但不是SUBSIZED,因为通常知道整个树的大小,而不知道子树的确切大小。
        另请参见:
                常数值
    • 方法详情

      • tryAdvance

        boolean tryAdvance(Consumer<? super T> action)
        如果剩余元素存在,则执行给定的操作,并返回true; 否则返回false。 如果此Spliterator是有序的(ORDERED),则按照遇到的顺序对下一个元素执行操作。 动作抛出的异常被转发给调用者。
        参数:
                action - 动作
        返回:
                如果在进入此方法时没有剩余的元素,则为false,否则为true。
        抛出:
                NullPointerException - 如果指定的操作为空
      • forEachRemaining

        default void forEachRemaining(Consumer<? super T> action)
        在当前线程中依次执行每个剩余元素的给定操作,直到所有元素都被处理或动作引发异常。 如果此Spliterator是ORDERED,则按相关顺序执行操作。 动作抛出的异常被转发给调用者。
        实现要求:
                默认实现反复调用tryAdvance(java.util.function.Consumer <?super T>),直到它返回false。 应尽可能覆盖。
        参数:
                action- 动作
        抛出:
                NullPointerException - 如果指定的操作为空
      • trySplit

        Spliterator<T> trySplit()
      • 如果此分割器可以被分区,则返回一个包含元素的Spliterator ,当从该方法返回时,它不会被该Spliterator 所覆盖。如果此Spliterator是ORDERED,则返回的Spliterator必须覆盖元素的严格前缀。除非这个Spliterator包含无数个元素,否则trySplit()的重复调用必须最终返回null。非空返回:1、在分解前报告的estimateSize()的值在分割之后必须大于或等于此值和返回的Spliterator的estimateSize();和2、如果这个Spliterator是SUBSIZED,那么在拆分之前,这个Spliterator的estimateSize()必须等于这个Spliterator和Spliterator之间的sumSize()之和。
      • 此方法可能由于任何原因返回null,包括空,遍历开始后无法拆分,数据结构约束和效率考虑。
      • API注:    一个理想的trySplit方法有效地(没有遍历)将其元素精确地分成两半,允许平衡并行计算。许多基于这个模型的分割仍然是非常有效的;
      •        例如,仅近似分裂几乎平衡的树,或者对于叶节点可以包含一个或两个元素的树,不能进一步分割这些节点。然而,平衡和/或过低效率的TrySplit机制的大偏差通常导致较差的并行性能。
      • 返回:    一个覆盖部分元素的分割器,如果此分割器无法拆分,则为null
      • estimateSize

        long estimateSize()
        返回forEachRemaining(java.util.function.Consumer <?super T>)遍历所遇到的元素数量的估计值,如果为无穷大,未知数或计算成本太高,则返回Long.MAX_VALUE。
        如果这个Spliterator是SIZED,并且还没有被部分地遍历或拆分,或者这个Spliterator是SUBSIZED,并且还没有被部分地遍历,则这个估计必须是一个完整的遍历所遇到的元素的精确计数。否则,此估计可能是任意不准确的,但必须按照trySplit()的调用指定减少。
        API注:
                即使是不精确的估计也通常是有用的并且这样的计算成本很低廉。例如,近似平衡的二叉树的子拼接器可以返回将元素的数量估计为其父代的数量的一半的值;如果根分割器不能保持准确的计数,则可以将尺寸估计为对应于其最大深度的两倍。
        返回:
                估计的大小,或Long.MAX_VALUE,如果无限的,未知的,或太高成本的计算。
      • getExactSizeIfKnown

        default long getExactSizeIfKnown()
        如果此Spliterator为SIZED,则返回estimateSize()的便利方法,否则为-1。
        实现要求:
                如果Spliterator报告了SIZED的特征,则默认实现将返回estimateSize()的结果,否则返回-1。
        返回:
                如果知道则返回确切的大小,,否则-1。
      • characteristics

        int characteristics()
        返回此Spliterator及其元素的一组特征。 结果表示为ORDERED,DISTINCT,SORTED,SIZED,NONNULL,IMMUTABLE,CONCURRENT,SUBSIZED中的OR值。 对于在给定的spliterator之前或之后调用trySplit的characteristics()的重复调用应该始终返回相同的结果。
        如果Spliterator报告不一致的特征集(从单个调用返回的或多个调用返回的),则不能保证使用此Spliterator的任何计算。
        API注:
                分裂之前的给定分配器的特性可能与分裂后的特性不同。 具体示例参见SIZED,SUBSIZED和CONCURRENT的特征值。
        返回:
                特征的表示
      • hasCharacteristics

        default boolean hasCharacteristics(int characteristics)
        如果此Spliterator的characteristics()包含所有给定的特征,则返回true。
        实现要求:
                如果给定特征的相应位被设置,默认实现将返回true。
        参数:
                characteristics - 检查的特点
        返回:
                如果所有指定的特征都存在,则为true,否则为false
      • getComparator

        default Comparator<? super T> getComparator()
        如果此Spliterator的源由比较器排序(SORTED),则返回该比较器。 如果源以自然顺序排序(SORTED),则返回null。 否则,如果源不是排序的(SORTED),则抛出IllegalStateException。
        实现要求:
                默认实现总是抛出IllegalStateException。
        返回:
                比较器,如果元素按照自然顺序排序,则为null。
        抛出:
                IllegalStateException - 如果Spliterator没有报告SORTED的特征。
来源: http://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html


原创粉丝点击