探索ArrayListSpliterator底層實現
阿新 • • 發佈:2020-12-18
前言
上次看ArrayList底層機制時把ArrayListSpliterator
放了放,現在回過頭來具體看看實現。
簡單粗暴
直接上程式碼吧!
static final class ArrayListSpliterator<E> implements Spliterator<E> { //指向當前集合物件 private final ArrayList<E> list; //當前索引,可能被trySplit和tryAdvance操作修改 private int index; //結束索引,未使用前為-1,使用後為list的size private int fence; //通過與modCount比較來判斷集合是否被修改,初始值與modCount相等 private int expectedModCount; /** * 初始化引數 * @param list 當前集合 * @param origin 起始索引 * @param fence 結束索引 * @param expectedModCount */ ArrayListSpliterator(ArrayList<E> list, int origin, int fence, int expectedModCount) { this.list = list; // OK if null unless traversed this.index = origin; this.fence = fence; this.expectedModCount = expectedModCount; } /** * 獲取結束索引 * 初始化expectedModCount與fence引數 * @return 結束索引 */ private int getFence() { // initialize fence to size on first use int hi; // (a specialized variant appears in method forEach) ArrayList<E> lst; if ((hi = fence) < 0) { if ((lst = list) == null) hi = fence = 0; else { expectedModCount = lst.modCount; hi = fence = lst.size; } } return hi; } /** * 在當前切割迭代器的基礎上再次拆分一個新的迭代器 * 若切割迭代器是可以拆分的,會返回新的一個切割迭代器,兩個迭代器平分原先迭代器中的元素 * 若切割迭代器無法拆分的話,則返回null * 拆分後原先迭代器必須修改起始索引,因為它的元素被拆分了(index = mid) * @return 新的切割迭代器或null */ public ArrayListSpliterator<E> trySplit() { int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; return (lo >= mid) ? null : // divide range in half unless too small new ArrayListSpliterator<E>(list, lo, index = mid, expectedModCount); } /** * 若存在剩餘元素,則對其下一個元素執行指定動作,並返回true * 若不存在剩餘元素,則返回false * 該方法是對單獨元素進行操作 * @param action 若存在剩餘元素,執行指定動作 * @return 是否存在剩餘元素 */ public boolean tryAdvance(Consumer<? super E> action) { if (action == null) throw new NullPointerException(); int hi = getFence(), i = index; if (i < hi) { index = i + 1; @SuppressWarnings("unchecked") E e = (E)list.elementData[i]; action.accept(e); if (list.modCount != expectedModCount) throw new ConcurrentModificationException(); return true; } return false; } /** * 遍歷剩餘元素,並執行指定動作 * @param action 若存在剩餘元素,執行指定動作 */ public void forEachRemaining(Consumer<? super E> action) { int i, hi, mc; // hoist accesses and checks from loop ArrayList<E> lst; Object[] a; if (action == null) throw new NullPointerException(); if ((lst = list) != null && (a = lst.elementData) != null) { 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]; action.accept(e); } if (lst.modCount == mc) return; } } throw new ConcurrentModificationException(); } /** * 獲取切割迭代器的元素個數 * 計算結束索引與起始索引之間的元素個數 * @return 切割迭代器的元素個數 */ public long estimateSize() { return (long) (getFence() - index); } /** * 獲取切割迭代器的特徵值 * ArrayList底層實現是陣列,故是有序、有實際大小、可重複、可存入null、屬於非執行緒安全、在遍歷時可新增修改替換元素 */ public int characteristics() { return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; } }
總結
-
分割迭代器可以單個(tryAdvance)或順序(多個)遍歷元素。
-
分割迭代器可拆分成若干個小型的分割迭代器來並行操作元素。
-
分割迭代器屬於非執行緒安全。
-
ArrayListSpliterator屬於後期繫結與快速失敗的分割迭代器。