码迷,mamicode.com
首页 > 其他好文 > 详细

探索ArrayListSpliterator底层实现

时间:2020-12-23 12:36:25      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:现在   bool   false   advance   初始   inter   iter   ati   前言   

前言

上次看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属于后期绑定与快速失败的分割迭代器。

探索ArrayListSpliterator底层实现

标签:现在   bool   false   advance   初始   inter   iter   ati   前言   

原文地址:https://www.cnblogs.com/zlia/p/14157309.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!