昨天我们分析了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,只是它在内部进行了巧妙的封装变换,这就是它的最大魅力所在。