JDK8并行迭代器Spliterator

Spliterator 和Iterator一樣,用于遍歷源的元素。
Spliterator是一個(gè)可分割迭代器splitable iterator,iterator是順序遍歷迭代器。
Spliterator API 旨在通過支持分解和單元素迭代來支持除順序遍歷之外的高效并行遍歷。 此外,通過 Spliterator 訪問元素的協(xié)議旨在施加比Iterator更小的每個(gè)元素開銷,并避免為hasNext()next()使用單獨(dú)的方法所涉及的固有競爭。

Iterator接口

public interface Iterator<E> {

    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

1.hasNext

單向移動(dòng),如果next將返回一個(gè)元素而不是拋出異常,則返回true 。使用hasNext()檢查序列中是否還有元素

boolean hasNext();

ArrayList
注:ArrayList中用size記錄實(shí)際數(shù)據(jù)的數(shù)量

public boolean hasNext() {
      //判斷指針是否到達(dá)了數(shù)組最后一個(gè)元素+1的位置,來判斷是否還有元素
      return cursor != size;
}

Vector
注:Vector中用elementCount記錄實(shí)際數(shù)據(jù)的數(shù)量

public boolean hasNext() {
      return cursor != elementCount;
}

2.next

第一次返回序列的第一個(gè)元素。返回值是Object,需要強(qiáng)制轉(zhuǎn)換成自己需要的類型

E next();

ArrayList

        public E next() {
            //同時(shí)修改檢查函數(shù)
            this.checkForComodification();
            //定義臨時(shí)的當(dāng)前元素的指針i并賦值
            int i = this.cursor;
            if (i >= ArrayList.this.size) {
                //如果當(dāng)前指針超出了范圍則拋出沒有足夠元素異常,同理于hasNext()判斷
                throw new NoSuchElementException();
            } else {
                /**
                 * 因?yàn)樵撍接蓄愂窃贏rrayList<E>內(nèi)部,所以可以直接調(diào)用ArrayList類中的屬性
                 * 該方法要返回元素?cái)?shù)組的其中一個(gè)內(nèi)容,在這里獲取元素?cái)?shù)組
                 */
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length) {
                    //通過直接檢查數(shù)組的長度,進(jìn)一步確認(rèn)數(shù)組是否被修改
                    throw new ConcurrentModificationException();
                } else {
                    //下一個(gè)元素指針+1
                    this.cursor = i + 1;
                    /**
                    * 因?yàn)橄乱粋€(gè)元素指針+1后,i就變成上一個(gè)元素了,所以先給上一個(gè)元素(lastRet)
                    * 賦值為i,然后返回第i個(gè)元素的值,即當(dāng)前元素的值
                    */
                    return elementData[this.lastRet = i];
                }
            }
        }

Vector

        public E next() {
            synchronized(Vector.this) {
                this.checkForComodification();
                int i = this.cursor;
                if (i >= Vector.this.elementCount) {
                    throw new NoSuchElementException();
                } else {
                    this.cursor = i + 1;
                    return Vector.this.elementData(this.lastRet = i);
                }
            }
        }

3.remove

將迭代器新返回的元素刪除。

default void remove() {
        throw new UnsupportedOperationException("remove");
    }

ArrayList

        public void remove() {
            //迭代器是根據(jù)上一個(gè)元素來刪除的,先判斷有沒有上一個(gè)元素
            if (this.lastRet < 0) {
                throw new IllegalStateException();
            } else {
                //同時(shí)修改檢查函數(shù)
                this.checkForComodification();
                try {
                    //調(diào)用外部類中的刪除方法
                    ArrayList.this.remove(this.lastRet);
                    /**
                     * 刪除成功后刪除元素后面的元素會(huì)整體前移一個(gè)位置所以下一個(gè)指針需要-1
                     * 這里直接把刪除元素的指針賦值給了下一個(gè)元素效果相當(dāng)于-1了
                     */
                    this.cursor = this.lastRet;
                    /**
                     * 由于沒刪除一個(gè)元素,上一個(gè)元素指針都會(huì)回歸到-1,所以該remove方法要配合
                     * next方法來用,使得每次調(diào)用該方法lastRet都>0
                     */
                    this.lastRet = -1;
                    /**
                     * 由于ArrayList.this.remove(lastRet)該方法中修改了modCount的值,所以
                     * 這里也要將expectedModCount的值與modCount同步
                     */
                    this.expectedModCount = ArrayList.this.modCount;
                } catch (IndexOutOfBoundsException var2) {
                    throw new ConcurrentModificationException();
                }
            }
        }

Vector

        public void remove() {
            if (this.lastRet == -1) {
                throw new IllegalStateException();
            } else {
                synchronized(Vector.this) {
                    this.checkForComodification();
                    Vector.this.remove(this.lastRet);
                    this.expectedModCount = Vector.this.modCount;
                }
                this.cursor = this.lastRet;
                this.lastRet = -1;
            }
        }

4.forEachRemaining

JDK8新增的函數(shù)式遍歷接口,對每個(gè)剩余元素執(zhí)行給定的操作,直到處理完所有元素或操作引發(fā)異常。
如果指定了該順序,則操作按迭代順序執(zhí)行。

default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }

ArrayList

        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            int size = ArrayList.this.size;
            int i = this.cursor;
            if (i < size) {
                Object[] es = ArrayList.this.elementData;
                if (i >= es.length) {
                    throw new ConcurrentModificationException();
                }
                while(i < size && ArrayList.this.modCount == this.expectedModCount) {
                    action.accept(ArrayList.elementAt(es, i));
                    ++i;
                }
                this.cursor = i;
                this.lastRet = i - 1;
                this.checkForComodification();
            }
        }

Vector

        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            synchronized(Vector.this) {
                int size = Vector.this.elementCount;
                int i = this.cursor;
                if (i < size) {
                    Object[] es = Vector.this.elementData;
                    if (i >= es.length) {
                        throw new ConcurrentModificationException();
                    } else {
                        while(i < size && Vector.this.modCount == this.expectedModCount) {
                            action.accept(Vector.elementAt(es, i++));
                        }

                        this.cursor = i;
                        this.lastRet = i - 1;
                        this.checkForComodification();
                    }
                }
            }
        }

該方法和使用通過hasNextnext方法遍歷有一定的區(qū)別,該方法只有在方法的最后更新了一次cursorlastRet。和nexthasNext方法共用了cursorlastRet,如果遍歷進(jìn)行到一半,然后使用另一種遍歷方式,那么遍歷不會(huì)從頭開始,而是從結(jié)束的地方開始

checkForComodification
主要用于驗(yàn)證在循環(huán)遍歷過程中,是否調(diào)用了ArrayListaddremove等操作,這些操作會(huì)增加modCount的值,導(dǎo)致該值和Iterator中的exprctedModCount值不相等,破壞原來的結(jié)構(gòu),遍歷出錯(cuò)。
ArrayListVector

        final void checkForComodification() {
            //通過檢查兩個(gè)修改計(jì)數(shù)器是否一致從而確定在迭代期間元素?cái)?shù)組有沒有被修改
            if (modCount != expectedModCount) {
                //如果被修改則拋出同時(shí)修改異常
                throw new ConcurrentModificationException();
            }
        }

Itr 迭代器類

ArrayList<E>Vector<E>類中都有私有的Itr內(nèi)部類
在Itr中重新定義了三個(gè)參數(shù):
cursor:當(dāng)前index
lastRet:上一個(gè)index,初始值-1
expectedModCount:修改次數(shù)

    private class Itr implements Iterator<E> {
        // 下一個(gè)元素的指針
        int cursor;    
        // 上一個(gè)元素的指針,如果沒有元素則是-1   
        int lastRet = -1; 
        //期望修改計(jì)數(shù)器,與修改計(jì)數(shù)器去比較從而確認(rèn)迭代期間元素?cái)?shù)組是否被修改
        int expectedModCount = modCount;
    }

ListItr 迭代器類

private class ListItr extends Itr implements ListIterator<E>
public interface ListIterator<E> extends Iterator<E>
public interface Iterator<E>

Itr 迭代器類實(shí)現(xiàn)了 Iterator 接口,ListItr迭代器類繼承Itr迭代器類,并且實(shí)現(xiàn)了 ListIterator 接口,所以 ListItr類的功能比 Itr 類更強(qiáng)大。ListItr可以說是Itr的升級版

 private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            super();
            cursor = index;
        }
        //只要cursor不等于0,就可以往回走
        public boolean hasPrevious() {
            return cursor != 0;
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor - 1;
        }

        @SuppressWarnings("unchecked")
        //查找前一個(gè)元素
        public E previous() {
            checkForComodification();
            //往回走,所以cursor-1給局部變量
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i;
            //因?yàn)間et的參數(shù)是i,所以lastRet肯定也應(yīng)該為i
            return (E) elementData[lastRet = i];
        }

        public void set(E e) {
            //說明執(zhí)行了remove或add后,還沒有進(jìn)行過next或previous操作
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.set(lastRet, e);
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            //add不用關(guān)心lastRet,即不在乎之前有沒有remove或add
            checkForComodification();

            try {
                int i = cursor;
                ArrayList.this.add(i, e);
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

Itr 類在迭代過程中不能修改 List 的結(jié)構(gòu)(如 add 操作),否則會(huì)拋出并發(fā)修改異常 ConcurrentModificationException,并且在 next方法之后才能 remove 元素,而 ListItr 類還支持在迭代過程中添加元素,對于 List 集合元素操作更加友好。所以對于List 集合迭代,最好使用 ListItr 迭代器類。

以上都是串行的迭代器,下面來介紹并行迭代器Spliterator
Spliterator是一個(gè)可分割迭代器(splitable iterator),可以和iterator順序遍歷迭代器一起看。
Jdk1.8發(fā)布后,對于并行處理的能力大大增強(qiáng),Spliterator就是為了并行遍歷元素而設(shè)計(jì)的一個(gè)迭代器,Jdk1.8中的集合框架中的數(shù)據(jù)結(jié)構(gòu)都默認(rèn)實(shí)現(xiàn)了spliterator

并行迭代器Spliterator

Spliterator接口

public interface Spliterator<T> {
    boolean tryAdvance(Consumer<? super T> action);

    default void forEachRemaining(Consumer<? super T> action) {
        do { } while (tryAdvance(action));
    }

    Spliterator<T> trySplit();

    long estimateSize();

    default long getExactSizeIfKnown() {
        return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
    }

    int characteristics();
    //判斷 Spliterator 是否包含這個(gè)特性
    default boolean hasCharacteristics(int characteristics) {
        return (characteristics() & characteristics) == characteristics;
    }
    //如果源是SORTED 類型的,且有比較器 Comparator 的話,則返回這個(gè) Comparator,如果是SORTED 類型的,但是沒有比較器,則返回 null , 除此之外,都拋出異常。
    default Comparator<? super T> getComparator() {
        throw new IllegalStateException();
    }
    //特性
    //表明元素是有序的,tryAdvance ,forEachRemaining和 trySplit 都會(huì)保證有序的進(jìn)行元素的處理。
    public static final int ORDERED    = 0x00000010;
    //表明元素是去重的,唯一性。 類似 Set 
    public static final int DISTINCT   = 0x00000001;
    //表明遍歷的順序是排好序的。或者是所有元素都是可比較的,或者是有特定的比較器。
    public static final int SORTED     = 0x00000004;
    //有這種屬性的 Spliterator 在遍歷和分割之前,estimateSize() 返回的大小是固定的,并且是準(zhǔn)確的。
    public static final int SIZED      = 0x00000040;
    //表明元素是非空的, 大部分并發(fā)的集合,隊(duì)列,Map 都可能會(huì)有這樣的特性。
    public static final int NONNULL    = 0x00000100;
    //表示元素源不能進(jìn)行結(jié)構(gòu)修改的特征值。遍歷期間無法添加,替換或刪除元素,否則拋出異常。
    public static final int IMMUTABLE  = 0x00000400;
    //表示可以在沒有外部同步的情況下由多個(gè)線程安全地同時(shí)修改元素源(允許添加,替換和/或刪除)。
    public static final int CONCURRENT = 0x00001000;
    //trySplit 返回的子分割迭代器都會(huì)是SIZED和SUBSIZED的。 分割成子,并且子的部分是固定大小的
    public static final int SUBSIZED = 0x00004000;
}

ArrayList的內(nèi)部類ArrayListSpliterator實(shí)現(xiàn)了Spliterator接口

static final class ArrayListSpliterator<E> implements Spliterator<E> {
        //用于存放ArrayList對象
        private final ArrayList<E> list;
        //起始位置(包含),advance/split操作時(shí)會(huì)修改
        private int index; 
        //結(jié)束位置(不包含),-1 表示到最后一個(gè)元素
        private int fence;
        //用于存放list的modCount
        private int expectedModCount; 

        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                             int expectedModCount) {
            this.list = list; 
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }

        //獲取結(jié)束位置(存在意義:首次初始化石需對fence和expectedModCount進(jìn)行賦值)
        private int getFence() { 
            int hi; 
            ArrayList<E> lst;
            //fence<0時(shí)(第一次初始化時(shí),fence才會(huì)小于0):
            if ((hi = fence) < 0) {
                //list 為 null時(shí),fence=0
                if ((lst = list) == null)
                    hi = fence = 0;
                else {
                    //否則,fence = list的長度。
                    expectedModCount = lst.modCount;
                    hi = fence = lst.size;
                }
            }
            return hi;
        }
}

1.tryAdvance

同時(shí)做了 hasNext() 以及 next() 的工作
類似于普通的Iterator,它會(huì)按順序一個(gè)一個(gè)使用 Spliterator 中的元素執(zhí)行action,并且如果還有其他元素要遍歷就返回 true,否則返回 false

boolean tryAdvance(Consumer<? super T> action);

ArrayList下的實(shí)現(xiàn)

    public boolean tryAdvance(Consumer<? super E> action) {
        //如果指定的操作為null則會(huì)拋出NullPointerException
        if (action == null)
            throw new NullPointerException();
        //hi為當(dāng)前的結(jié)束位置
        //i 為起始位置
        int hi = getFence(), i = index;
        //還有剩余元素未處理時(shí)
        if (i < hi) {
            //處理i位置,index+1
            index = i + 1;
            @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
            action.accept(e);
            //遍歷時(shí),結(jié)構(gòu)發(fā)生變更,拋錯(cuò)
            if (list.modCount != expectedModCount)
                throw new ConcurrentModificationException();
            return true;
        }
        return false;
    }

2.forEachRemaining

默認(rèn)方法,在當(dāng)前線程中對每個(gè)剩余元素執(zhí)行給定操作,直到所有元素都已處理或操作拋出異常為止,如果源是有序的,遍歷也是有序的。
實(shí)現(xiàn):重復(fù)調(diào)用tryAdvance(java.util.function.Consumer <? super T>),直到它返回false。應(yīng)該盡可能地覆蓋它

default void forEachRemaining(Consumer<? super T> action) {
        do { } while (tryAdvance(action));
    }

注:方法體中的 do {} 是空的,這個(gè)是因?yàn)?tryAdvance() 方法本身就完成了兩個(gè)操作 hasNext() 以及 next(),所以方法體中不需要有任何操作了。這個(gè)是函數(shù)式編程帶來的好處。以及與命令式編程的區(qū)別。
ArrayList下的實(shí)現(xiàn)

        public void forEachRemaining(Consumer<? super E> action) {
            int i, hi, mc; 
            ArrayList<E> lst; Object[] a;
            if (action == null)
                throw new NullPointerException();
            if ((lst = list) != null && (a = lst.elementData) != null) {
                //當(dāng)fence<0時(shí),表示fence和expectedModCount未初始化
                if ((hi = fence) < 0) {
                    mc = lst.modCount;
                    hi = lst.size;
                }
                else
                    mc = expectedModCount;
                if ((i = index) >= 0 && (index = hi) <= a.length) {
                    for (; i < hi; ++i) {
                        @SuppressWarnings("unchecked") E e = (E) a[i];
                        //調(diào)用action.accept處理元素
                        action.accept(e);
                    }
                    //遍歷時(shí)發(fā)生結(jié)構(gòu)變更時(shí)拋出異常
                    if (lst.modCount == mc)
                        return;
                }
            }
            throw new ConcurrentModificationException();
        }

3.trySplit

嘗試切分源來的 Spliterator,返回一個(gè)新分割出的Spliterator實(shí)例,返回的是分割出來的那一部分?jǐn)?shù)據(jù),原有的數(shù)據(jù)集將不再包含這部分?jǐn)?shù)據(jù)集合。兩者沒有交集。剩下的可以繼續(xù)分割,或者不可以繼續(xù)分割,返回null
如果是原有數(shù)據(jù)集合是 ORDERD 的,分出來的也是有序的。

Spliterator<T> trySplit();

官方接口說明:理想的trySplit方法有效地(無需遍歷)將其元素精確地一分為二,從而實(shí)現(xiàn)平衡的并行計(jì)算。 許多偏離這一理想的方法仍然非常有效; 例如,僅對近似平衡的樹進(jìn)行近似分裂,或者對于葉子節(jié)點(diǎn)可能包含一個(gè)或兩個(gè)元素的樹,未能進(jìn)一步分裂這些節(jié)點(diǎn)。 然而,平衡的大偏差和/或過度低效的trySplit機(jī)制通常會(huì)導(dǎo)致并行性能不佳。
ArrayList下的實(shí)現(xiàn)

public ArrayListSpliterator<E> trySplit() {
     //hi為當(dāng)前的結(jié)束位置
     //lo 為起始位置
     //計(jì)算中間的位置
     int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
     //當(dāng)lo>=mid,表示不能在分割,返回null
     //當(dāng)lo<mid時(shí),可分割,切割(lo,mid)出去,同時(shí)更新index=mid
     return (lo >= mid) ? null : 
          new ArrayListSpliterator<E>(list, lo, index = mid,expectedModCount);
}

4.estimateSize

返回對forEachRemaining遍歷將遇到的元素?cái)?shù)量的估計(jì),如果無限、未知或計(jì)算成本太高,則返回Long.MAX_VALUE,也就是2^63-1

long estimateSize();

官方接口說明:即使是不精確的估計(jì)也常常有用且計(jì)算成本低。
例如,近似平衡二叉樹的子分裂器可能會(huì)返回一個(gè)值,該值估計(jì)元素?cái)?shù)量是其父元素?cái)?shù)量的一半; 如果根 Spliterator 沒有保持準(zhǔn)確的計(jì)數(shù),它可以將大小估計(jì)為對應(yīng)于其最大深度的 2 的冪。

ArrayList下的實(shí)現(xiàn)

public long estimateSize() {
    return (long) (getFence() - index);
}

分割迭代器主要是用來對源數(shù)據(jù)元素進(jìn)行遍歷和分區(qū)。分割迭代器的源數(shù)據(jù)可以是數(shù)組、集合、IO通道以及生成器函數(shù)(比如Stream的iterate方法)。
分割迭代器遍歷元素有兩種方式:
1.通過 tryAdvance 方法單個(gè)元素的遍歷。
2.通過forEachRemaining 方法順序的按塊遍歷。

Spliterator 也可以將它的一些元素(使用trySplit )作為另一個(gè) Spliterator 進(jìn)行分區(qū),以用于可能的并行操作。
官方接口說明:
Spliterators 和Iterator一樣,用于遍歷源的元素。 Spliterator API 旨在通過支持分解和單元素迭代來支持除順序遍歷之外的高效并行遍歷。 此外,通過 Spliterator 訪問元素的協(xié)議旨在施加比Iterator更小的每個(gè)元素開銷,并避免為hasNext()next()使用單獨(dú)的方法所涉及的固有競爭。

衍生接口OfPrimitive

public interface OfPrimitive<T, T_CONS, T_SPLITR 
                          extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> 
                          extends Spliterator<T> {
        @Override
        T_SPLITR trySplit();

        @SuppressWarnings("overloads")
        boolean tryAdvance(T_CONS action);

        @SuppressWarnings("overloads")
        default void forEachRemaining(T_CONS action) {
            do { } while (tryAdvance(action));
        }
    }

OfPrimitive重載了Spliterator的tryAdvanceforEachRemaining方法。用于實(shí)現(xiàn)特化的分割迭代器。
基于OfPrimitive接口,又衍生出了OfIntOfLongOfDouble等專門用來處理intlongdouble等分割迭代器接口

public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt>
public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong>
public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble>

為int 、 long和double值提供了Spliterator原始子類型Spliterator 。
tryAdvance(Consumer)forEachRemaining(Consumer)的子類型默認(rèn)實(shí)現(xiàn)框原始值到其相應(yīng)包裝器類的實(shí)例。
這種裝箱可能會(huì)破壞通過使用原始特化獲得的任何性能優(yōu)勢。 為避免裝箱,應(yīng)使用相應(yīng)的基于基元的方法

Spliterators類

具體實(shí)現(xiàn)都在java.util.Spliterators類中

public final class Spliterators

實(shí)現(xiàn)了針對int[]long[]double[]數(shù)據(jù)分割迭代器,和ArrayList差不多

內(nèi)部類IntArraySpliterator

static final class IntArraySpliterator implements Spliterator.OfInt {
        private final int[] array;
        private int index;        
        private final int fence; 
        //用于記錄特征值
        private final int characteristics;

        // 初始構(gòu)造器
        public IntArraySpliterator(int[] array, int additionalCharacteristics) {
            this(array, 0, array.length, additionalCharacteristics);
        }

        public IntArraySpliterator(int[] array, int origin, 
                                   int fence, int additionalCharacteristics) {
            this.array = array;
            this.index = origin;
            this.fence = fence;
            this.characteristics = additionalCharacteristics 
                                 | Spliterator.SIZED 
                                 | Spliterator.SUBSIZED;
        }
        
        @Override
        public OfInt trySplit() {
            //分割
            int lo = index, mid = (lo + fence) >>> 1;
            return (lo >= mid)
                   ? null
                   : new IntArraySpliterator(array, lo, index = mid, characteristics);
        }

        @Override
        public void forEachRemaining(IntConsumer action) {
            int[] a; int i, hi; 
            if (action == null)
                throw new NullPointerException();
            if ((a = array).length >= (hi = fence) &&
                (i = index) >= 0 && i < (index = hi)) {
                do { action.accept(a[i]); } while (++i < hi);
            }
        }

        @Override
        public boolean tryAdvance(IntConsumer action) {
            if (action == null)
                throw new NullPointerException();
            if (index >= 0 && index < fence) {
                action.accept(array[index++]);
                return true;
            }
            return false;
        }

        @Override
        public long estimateSize() { return (long)(fence - index); }

    }

內(nèi)部類LongArraySpliterator

static final class LongArraySpliterator implements Spliterator.OfLong {
        private final long[] array;
        private int index;       
        private final int fence;  
        private final int characteristics;

        public LongArraySpliterator(long[] array, int additionalCharacteristics) {
            this(array, 0, array.length, additionalCharacteristics);
        }

        public LongArraySpliterator(long[] array, int origin, 
                                    int fence, int additionalCharacteristics) {
            this.array = array;
            this.index = origin;
            this.fence = fence;
            this.characteristics = additionalCharacteristics 
                                 | Spliterator.SIZED 
                                 | Spliterator.SUBSIZED;
        }

        @Override
        public OfLong trySplit() {
            int lo = index, mid = (lo + fence) >>> 1;
            return (lo >= mid)
                   ? null
                   : new LongArraySpliterator(array, lo, index = mid, characteristics);
        }

        @Override
        public void forEachRemaining(LongConsumer action) {
            long[] a; int i, hi; 
            if (action == null)
                throw new NullPointerException();
            if ((a = array).length >= (hi = fence) &&
                (i = index) >= 0 && i < (index = hi)) {
                do { action.accept(a[i]); } while (++i < hi);
            }
        }

        @Override
        public boolean tryAdvance(LongConsumer action) {
            if (action == null)
                throw new NullPointerException();
            if (index >= 0 && index < fence) {
                action.accept(array[index++]);
                return true;
            }
            return false;
        }

        @Override
        public long estimateSize() { return (long)(fence - index); }
    }

內(nèi)部類DoubleArraySpliterator

static final class DoubleArraySpliterator implements Spliterator.OfDouble {
        private final double[] array;
        private int index;        
        private final int fence;  
        private final int characteristics;

        public DoubleArraySpliterator(double[] array, int additionalCharacteristics) {
            this(array, 0, array.length, additionalCharacteristics);
        }

        public DoubleArraySpliterator(double[] array, int origin, 
                                      int fence, int additionalCharacteristics) {
            this.array = array;
            this.index = origin;
            this.fence = fence;
            this.characteristics = additionalCharacteristics 
                                 | Spliterator.SIZED 
                                 | Spliterator.SUBSIZED;
        }

        @Override
        public OfDouble trySplit() {
            int lo = index, mid = (lo + fence) >>> 1;
            return (lo >= mid)
                   ? null
                   : new DoubleArraySpliterator(array, lo, index = mid, characteristics);
        }

        @Override
        public void forEachRemaining(DoubleConsumer action) {
            double[] a; int i, hi; 
            if (action == null)
                throw new NullPointerException();
            if ((a = array).length >= (hi = fence) &&
                (i = index) >= 0 && i < (index = hi)) {
                do { action.accept(a[i]); } while (++i < hi);
            }
        }

        @Override
        public boolean tryAdvance(DoubleConsumer action) {
            if (action == null)
                throw new NullPointerException();
            if (index >= 0 && index < fence) {
                action.accept(array[index++]);
                return true;
            }
            return false;
        }

        @Override
        public long estimateSize() { return (long)(fence - index); }
    }

與ArrayList不同的是,array是實(shí)現(xiàn)聲明的,因此不必?fù)?dān)心遍歷過程中發(fā)生結(jié)構(gòu)變更。

參考文章:

https://www.cnblogs.com/allmignt/p/12353737.html
https://blog.csdn.net/lh513828570/article/details/56673804
https://www.cnblogs.com/qingshanli/p/11756940.html#_label1_0

官方文檔:

https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html
https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,794評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內(nèi)容