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();
}
}
}
}
該方法和使用通過hasNext
和next
方法遍歷有一定的區(qū)別,該方法只有在方法的最后更新了一次cursor
和lastRet
。和next
,hasNext
方法共用了cursor
和lastRet
,如果遍歷進(jìn)行到一半,然后使用另一種遍歷方式,那么遍歷不會(huì)從頭開始,而是從結(jié)束的地方開始
checkForComodification
主要用于驗(yàn)證在循環(huán)遍歷過程中,是否調(diào)用了ArrayList
的add
,remove
等操作,這些操作會(huì)增加modCount
的值,導(dǎo)致該值和Iterator
中的exprctedModCount
值不相等,破壞原來的結(jié)構(gòu),遍歷出錯(cuò)。
ArrayList
和Vector
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的tryAdvance
和forEachRemaining
方法。用于實(shí)現(xiàn)特化的分割迭代器。
基于OfPrimitive
接口,又衍生出了OfInt
、OfLong
、OfDouble
等專門用來處理int
、long
、double
等分割迭代器接口
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