首页 > 代码库 > JAVA Collection 源码分析(二)之SubList

JAVA Collection 源码分析(二)之SubList

  昨天我们分析了ArrayList的源码,我们可以看到,在其中还有一个类,名为SubList,其继承了AbstractList。

// AbstractList类型的引用,所有继承了AbstractList都可以传进来 private final AbstractList<E> parent;//       这个是其实就是parent的偏移量,从parent中的第几个元素开始的        private final int parentOffset;        private final int offset;        int size;        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,只是这里面// 用了一个很巧妙的方法,用了offset的这个偏移量,他就指向我们截取过后的list的首个元素,// 从下面的方法我们也可以看出,真是巧妙的数据结构的设计
// 以下就是它实现的具体方法,主要是注意到,现在的index都是相对于offset以后的位置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;        }

  在subLIst我们可以找到我们昨天分析的modCount的答案,为什么对数组每次操作都要进行modCount++的操作,我们可以找到checkForComodification()这个方法,其实就是在迭代中,校验expectedModCount 等不等于 ArrayList.this.modCount

因为每次对数组进行操作的时候,modCount都会进行++,所以如果不相等的,就会报错,并发所产生的错误。

  所以Sublist其实就是还是原来的List,只是它在内部进行了巧妙的封装变换,这就是它的最大魅力所在。