ArrayList源码分析:内部迭代器实现(二)

一、 提供公开的iterator方法以内部类的形式Itr是ListItr的父类:

1.iterator方法:

    public Iterator<E> iterator() {
        return new Itr();
    }

2.hasNext方法和next方法:

具体内部信息如下:

private class Itr implements Iterator<E> {//实现了Iterator接口
        int cursor;       // index of next element to return 下一个返回元素的下标,无需初始化,在类的准备阶段自动赋值为0
        int lastRet = -1; // index of last element returned; -1 if no such 最后一元素的返回值
        int expectedModCount = modCount;//增减操作次数

        Itr() {}//构造方法

        public boolean hasNext() {
            return cursor != size;//很好理解的是cursor等于size时,next元素就超出下标 从而异常
        }
        
		@SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();//检查当前list元素是否被修改,生成迭代器之后,若元素值发生了数量的变化,就会抛出异常,修改不会产生异常,由此可以看出ArrayList是线程不安全的,会出现读不一致问题
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];//返回对应下标的的元素
        }

3.remove方法:

   public void remove() {//iterator内部的移除方法
            if (lastRet < 0)//所有移除之后就会有异常
                throw new IllegalStateException();
            checkForComodification();//检验是否原List数量发生了变化

            try {
                ArrayList.this.remove(lastRet);//调用ArrayList自身的remove方法
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

4.forEachRemaining方法:

		@Override//重写的迭代器方法
        @SuppressWarnings("unchecked")//遍历剩余的元素,由此实现二分查找算法
        public void forEachRemaining(Consumer<? super E> consumer){//接收一个consumer接口重写 accpt方法
            Objects.requireNonNull(consumer);//验证不为空
            final int size = ArrayList.this.size;//
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();//都要进行元素变化检验
        }

二、第二个内部类ListItr

1.带参数:参数代表迭代指定数组下标,0<index<this.elementData.size,从指定index开始遍历
   public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)//下标校验
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }
2.无参:可从初始位置遍历
  public ListIterator<E> listIterator() {//通过new内部类实例实现List双向遍历
        return new ListItr(0);
    }
3.设计原理逻辑:都是私有化内部类,提供公共的获取方法。
private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            super();
            cursor = index;
        }
        
        public boolean hasPrevious() {//判断是否前驱元素
            return cursor != 0;
        }

        public int nextIndex() { //获取下一个元素的下标
            return cursor;
        }

        public int previousIndex() {//获取前驱元素下标
            return cursor - 1;
        }

        @SuppressWarnings("unchecked")
        public E previous() {
            checkForComodification();//这个函数很简单就是校验expectedModcount和真实ModCount是否相等,从而决定程序是否继续执行,还是异常终止
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i;
            return (E) elementData[lastRet = i];
        }

        public void set(E e) {//只能给当前遍历到的值进行赋值
            if (lastRet < 0)//检验下标合理性
                throw new IllegalStateException();
            checkForComodification();//检查元素变动

            try {
                ArrayList.this.set(lastRet, e);//通过类内部
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();//元素变动检验

            try {
                int i = cursor;
                ArrayList.this.add(i, e);//通过调用类内部的方法实现增加
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

三、第三个内部类 subList

1**函数说明:**获取对应区间的子List,第一个代表起始位置,第二个代表结束位置
 public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);//下标范围检验
        return new SubList(this, 0, fromIndex, toIndex);
    }
2.内部类具体构成:
    private class SubList extends AbstractList<E> implements RandomAccess {
        private final AbstractList<E> parent;//用于接收父级List
        private final int parentOffset;//父下标偏移量
        private final int offset;//内部偏移量,初始化为0
        int size; //List元素个数

        SubList(AbstractList<E> parent,
                int offset, int fromIndex, int toIndex) {//构造方法:用于构建子类对象
            this.parent = parent;
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = ArrayList.this.modCount;//由此可知在生成子List之后不可以再通过原类实例进行元素数量的更改
        }

        public E set(int index, E e) {
            rangeCheck(index);
            checkForComodification();
            E oldValue = ArrayList.this.elementData(offset + index);
            ArrayList.this.elementData[offset + index] = e;
            return oldValue;
        }

        public E get(int index) {
            rangeCheck(index);
            checkForComodification();
            return ArrayList.this.elementData(offset + index);
        }

        public int size() {
            checkForComodification();
            return this.size;
        }

        public void add(int index, E e) {
            rangeCheckForAdd(index);
            checkForComodification();
            parent.add(parentOffset + index, e);
            this.modCount = parent.modCount;
            this.size++;
        }

        public E remove(int index) {
            rangeCheck(index);
            checkForComodification();
            E result = parent.remove(parentOffset + index);
            this.modCount = parent.modCount;
            this.size--;
            return result;
        }

        protected void removeRange(int fromIndex, int toIndex) {
            checkForComodification();
            parent.removeRange(parentOffset + fromIndex,
                               parentOffset + toIndex);
            this.modCount = parent.modCount;
            this.size -= toIndex - fromIndex;
        }

        public boolean addAll(Collection<? extends E> c) {
            return addAll(this.size, c);
        }

        public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);
            int cSize = c.size();
            if (cSize==0)
                return false;

            checkForComodification();
            parent.addAll(parentOffset + index, c);
            this.modCount = parent.modCount;
            this.size += cSize;
            return true;
        }

        public Iterator<E> iterator() {//生成对应子类的迭代器
            return listIterator();
        }

**注释:**此处采用直接内部实现一个Listiterator接口,然后用ListIterator接收,同时也要保证List元素个数不可变性,重写需要重写的方法,对于元素的更改内部调用ArrayList的实例方法,要进行modCount修改。

3.内部迭代器实现逻辑
        public ListIterator<E> listIterator(final int index) {//子List也可以使用迭代器
            checkForComodification();//元素数量变动detect
            rangeCheckForAdd(index);//元素越界检验
            final int offset = this.offset;//此处的this指的是SubList实例引用

            return new ListIterator<E>() {//匿名内部类的形式直接实现一个接口
                int cursor = index;
                int lastRet = -1;
                int expectedModCount = ArrayList.this.modCount;//ArrayList.this 指的是当前ArrayList实例的引用

                public boolean hasNext() {
                    return cursor != SubList.this.size;//因为此时存在父类关系,拥有三个对象实例
                }

                @SuppressWarnings("unchecked")
                public E next() {
                    checkForComodification();
                    int i = cursor;
                    if (i >= SubList.this.size)
                        throw new NoSuchElementException();
                    Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i + 1;
                    return (E) elementData[offset + (lastRet = i)];
                }

                public boolean hasPrevious() {
                    return cursor != 0;
                }

                @SuppressWarnings("unchecked")
                public E previous() {
                    checkForComodification();
                    int i = cursor - 1;
                    if (i < 0)
                        throw new NoSuchElementException();
                    Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i;
                    return (E) elementData[offset + (lastRet = i)];
                }

                @SuppressWarnings("unchecked")
                public void forEachRemaining(Consumer<? super E> consumer) {
                    Objects.requireNonNull(consumer);
                    final int size = SubList.this.size;
                    int i = cursor;
                    if (i >= size) {
                        return;
                    }
                    final Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length) {
                        throw new ConcurrentModificationException();
                    }
                    while (i != size && modCount == expectedModCount) {
                        consumer.accept((E) elementData[offset + (i++)]);
                    }
                    // update once at end of iteration to reduce heap write traffic
                    lastRet = cursor = i;
                    checkForComodification();
                }

                public int nextIndex() {
                    return cursor;
                }

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

                public void remove() {
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try {
                        SubList.this.remove(lastRet);
                        cursor = lastRet;
                        lastRet = -1;
                        expectedModCount = ArrayList.this.modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                public void set(E e) {
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

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

                public void add(E e) {
                    checkForComodification();

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

                final void checkForComodification() {
                    if (expectedModCount != ArrayList.this.modCount)
                        throw new ConcurrentModificationException();
                }
            };
        }
        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, offset, fromIndex, toIndex);
        }

        private void rangeCheck(int index) {
            if (index < 0 || index >= this.size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

        private void rangeCheckForAdd(int index) {
            if (index < 0 || index > this.size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

        private String outOfBoundsMsg(int index) {
            return "Index: "+index+", Size: "+this.size;
        }

        private void checkForComodification() {
            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
        }
        }

四、第四个不是内部类而是static-nested类ArrayListSpliterator

1.是一个静态nested类提供全局使用:

SubList调用:

       public Spliterator<E> spliterator() {//公共的方法 获取ArrayListSpliterator<E> 
            checkForComodification();
            return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                               offset + this.size, this.modCount);
        }
    }

ArrayList实例方法:

  	@Override
    public Spliterator<E> spliterator() {
        return new ArrayListSpliterator<>(this, 0, -1, 0);
    }
2.静态嵌套类类具体实现:

具体作用就是二分遍历:

 static final class ArrayListSpliterator<E> implements Spliterator<E> {//实现了Spliterator接口
 
        private final ArrayList<E> list;//用于接收List
        private int index; // current index, modified on advance/split
        private int fence; // -1 until used; then one past last index
        private int expectedModCount; // initialized when fence set

        /** Create new spliterator covering the given  range */
        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;
        }

        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;
        }

        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);
        }

        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;
        }

        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();
        }

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

        public int characteristics() {
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }

**注:**本文是对源码梳理,关于各个方法的使用场景没有做过多的剖析,可以清楚的理清迭代器的实现原理,深刻的认识到ArryList是线程不安全的,并且Itr用于顺向遍历,而ListItr完美的解决无法获取前驱元素的问题,SubList解决了遍历起始位置的问题,使得获取ArrayList值方法变得多样性,Spliterator的构建可以用于实现一定的算法来提高程序运行效率,从时间复杂度和空间复杂度优化方案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值