src/java.base/share/classes/java/util/ArrayList.java

Print this page
rev 11824 : [mq]: 8079136-NestedSubList

@@ -1007,40 +1007,28 @@
     public List<E> subList(int fromIndex, int toIndex) {
         subListRangeCheck(fromIndex, toIndex, size);
         return new SubList(this, 0, fromIndex, toIndex);
     }
 
-    static void subListRangeCheck(int fromIndex, int toIndex, int size) {
-        if (fromIndex < 0)
-            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
-        if (toIndex > size)
-            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
-        if (fromIndex > toIndex)
-            throw new IllegalArgumentException("fromIndex(" + fromIndex +
-                                               ") > toIndex(" + toIndex + ")");
-    }
-
     private class SubList extends AbstractList<E> implements RandomAccess {
         private final AbstractList<E> 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;
         }
 
-        public E set(int index, E e) {
+        public E set(int index, E element) {
             rangeCheck(index);
             checkForComodification();
             E oldValue = ArrayList.this.elementData(offset + index);
-            ArrayList.this.elementData[offset + index] = e;
+            ArrayList.this.elementData[offset + index] = element;
             return oldValue;
         }
 
         public E get(int index) {
             rangeCheck(index);

@@ -1051,60 +1039,57 @@
         public int size() {
             checkForComodification();
             return this.size;
         }
 
-        public void add(int index, E e) {
+        public void add(int index, E element) {
             rangeCheckForAdd(index);
             checkForComodification();
-            parent.add(parentOffset + index, e);
-            this.modCount = parent.modCount;
-            this.size++;
+            ArrayList.this.add(offset + index, element);
+            updateSizeAndModCount(1, ArrayList.this.modCount);
         }
 
         public E remove(int index) {
             rangeCheck(index);
             checkForComodification();
-            E result = parent.remove(parentOffset + index);
-            this.modCount = parent.modCount;
-            this.size--;
+            E result = ArrayList.this.remove(offset + index);
+            updateSizeAndModCount(-1, ArrayList.this.modCount);
             return result;
         }
 
         protected void removeRange(int fromIndex, int toIndex) {
             checkForComodification();
-            parent.removeRange(parentOffset + fromIndex,
-                               parentOffset + toIndex);
-            this.modCount = parent.modCount;
-            this.size -= toIndex - fromIndex;
+            ArrayList.this.removeRange(offset + fromIndex,
+                                       offset + toIndex);
+            updateSizeAndModCount(fromIndex - toIndex,
+                                  ArrayList.this.modCount);
         }
 
         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)
+            if (cSize == 0)
                 return false;
 
             checkForComodification();
-            parent.addAll(parentOffset + index, c);
-            this.modCount = parent.modCount;
-            this.size += cSize;
+            ArrayList.this.addAll(offset + index, c);
+            updateSizeAndModCount(cSize,
+                                  ArrayList.this.modCount);
             return true;
         }
 
         public Iterator<E> iterator() {
             return listIterator();
         }
 
         public ListIterator<E> listIterator(final int index) {
             checkForComodification();
             rangeCheckForAdd(index);
-            final int offset = this.offset;
 
             return new ListIterator<E>() {
                 int cursor = index;
                 int lastRet = -1;
                 int expectedModCount = ArrayList.this.modCount;

@@ -1219,11 +1204,11 @@
             };
         }
 
         public List<E> subList(int fromIndex, int toIndex) {
             subListRangeCheck(fromIndex, toIndex, size);
-            return new SubList(this, offset, fromIndex, toIndex);
+            return ArrayList.this.new SubList(this, offset, fromIndex, toIndex);
         }
 
         private void rangeCheck(int index) {
             if (index < 0 || index >= this.size)
                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

@@ -1233,18 +1218,28 @@
             if (index < 0 || index > this.size)
                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
         }
 
         private String outOfBoundsMsg(int index) {
-            return "Index: "+index+", Size: "+this.size;
+            return "Index: " + index + ", Size: " + this.size;
         }
 
         private void checkForComodification() {
             if (ArrayList.this.modCount != this.modCount)
                 throw new ConcurrentModificationException();
         }
 
+        private void updateSizeAndModCount(int sizeChange, int modCount) {
+            AbstractList<E> alist = this;
+            do {
+                SubList slist = (SubList)alist;
+                slist.size += sizeChange;
+                slist.modCount = modCount;
+                alist = slist.parent;
+            } while (alist instanceof ArrayList.SubList);
+        }
+
         public Spliterator<E> spliterator() {
             checkForComodification();
             return new ArrayListSpliterator<>(ArrayList.this, offset,
                                               offset + this.size, this.modCount);
         }