< prev index next >

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

Print this page
rev 13796 : imported patch 8079136-Nested-SubLists

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -460,14 +460,13 @@
      * {@inheritDoc}
      *
      * @implSpec
      * This implementation returns a list that subclasses
      * {@code AbstractList}.  The subclass stores, in private fields, the
-     * offset of the subList within the backing list, the size of the subList
-     * (which can change over its lifetime), and the expected
-     * {@code modCount} value of the backing list.  There are two variants
-     * of the subclass, one of which implements {@code RandomAccess}.
+     * size of the subList (which can change over its lifetime), and the
+     * expected {@code modCount} value of the backing list.  There are two
+     * variants of the subclass, one of which implements {@code RandomAccess}.
      * If this list implements {@code RandomAccess} the returned list will
      * be an instance of the subclass that implements {@code RandomAccess}.
      *
      * <p>The subclass's {@code set(int, E)}, {@code get(int)},
      * {@code add(int, E)}, {@code remove(int)}, {@code addAll(int,

@@ -491,15 +490,26 @@
      *         {@code (fromIndex < 0 || toIndex > size)}
      * @throws IllegalArgumentException if the endpoint indices are out of order
      *         {@code (fromIndex > toIndex)}
      */
     public List<E> subList(int fromIndex, int toIndex) {
+        subListRangeCheck(fromIndex, toIndex, size());
         return (this instanceof RandomAccess ?
                 new RandomAccessSubList<>(this, fromIndex, toIndex) :
                 new SubList<>(this, 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 + ")");
+    }
+
     // Comparison and hashing
 
     /**
      * Compares the specified object with this list for equality.  Returns
      * {@code true} if and only if the specified object is also a list, both

@@ -621,70 +631,76 @@
     }
 
     private String outOfBoundsMsg(int index) {
         return "Index: "+index+", Size: "+size();
     }
-}
 
-class SubList<E> extends AbstractList<E> {
-    private final AbstractList<E> l;
+    private static class SubList<E> extends AbstractList<E> {
+        private final AbstractList<E> root;
+        private final SubList<E> parent;
     private final int offset;
-    private int size;
+        protected int size;
 
-    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
-        if (fromIndex < 0)
-            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
-        if (toIndex > list.size())
-            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
-        if (fromIndex > toIndex)
-            throw new IllegalArgumentException("fromIndex(" + fromIndex +
-                                               ") > toIndex(" + toIndex + ")");
-        l = list;
-        offset = fromIndex;
-        size = toIndex - fromIndex;
-        this.modCount = l.modCount;
+        /**
+         * Constructs a sublist of an arbitrary AbstractList, which is
+         * not a SubList itself.
+         */
+        public SubList(AbstractList<E> root, int fromIndex, int toIndex) {
+            this.root = root;
+            this.parent = null;
+            this.offset = fromIndex;
+            this.size = toIndex - fromIndex;
+            this.modCount = root.modCount;
+        }
+
+        /**
+         * Constructs a sublist of another SubList.
+         */
+        protected SubList(SubList<E> parent, int fromIndex, int toIndex) {
+            this.root = parent.root;
+            this.parent = parent;
+            this.offset = parent.offset + fromIndex;
+            this.size = toIndex - fromIndex;
+            this.modCount = root.modCount;
     }
 
     public E set(int index, E element) {
-        rangeCheck(index);
+            Objects.checkIndex(index, size);
         checkForComodification();
-        return l.set(index+offset, element);
+            return root.set(offset + index, element);
     }
 
     public E get(int index) {
-        rangeCheck(index);
+            Objects.checkIndex(index, size);
         checkForComodification();
-        return l.get(index+offset);
+            return root.get(offset + index);
     }
 
     public int size() {
         checkForComodification();
         return size;
     }
 
     public void add(int index, E element) {
         rangeCheckForAdd(index);
         checkForComodification();
-        l.add(index+offset, element);
-        this.modCount = l.modCount;
-        size++;
+            root.add(offset + index, element);
+            updateSizeAndModCount(1);
     }
 
     public E remove(int index) {
-        rangeCheck(index);
+            Objects.checkIndex(index, size);
         checkForComodification();
-        E result = l.remove(index+offset);
-        this.modCount = l.modCount;
-        size--;
+            E result = root.remove(offset + index);
+            updateSizeAndModCount(-1);
         return result;
     }
 
     protected void removeRange(int fromIndex, int toIndex) {
         checkForComodification();
-        l.removeRange(fromIndex+offset, toIndex+offset);
-        this.modCount = l.modCount;
-        size -= (toIndex-fromIndex);
+            root.removeRange(offset + fromIndex, offset + toIndex);
+            updateSizeAndModCount(fromIndex - toIndex);
     }
 
     public boolean addAll(Collection<? extends E> c) {
         return addAll(size, c);
     }

@@ -692,28 +708,27 @@
     public boolean addAll(int index, Collection<? extends E> c) {
         rangeCheckForAdd(index);
         int cSize = c.size();
         if (cSize==0)
             return false;
-
         checkForComodification();
-        l.addAll(offset+index, c);
-        this.modCount = l.modCount;
-        size += cSize;
+            root.addAll(offset + index, c);
+            updateSizeAndModCount(cSize);
         return true;
     }
 
     public Iterator<E> iterator() {
         return listIterator();
     }
 
-    public ListIterator<E> listIterator(final int index) {
+        public ListIterator<E> listIterator(int index) {
         checkForComodification();
         rangeCheckForAdd(index);
 
         return new ListIterator<E>() {
-            private final ListIterator<E> i = l.listIterator(index+offset);
+                private final ListIterator<E> i =
+                        root.listIterator(offset + index);
 
             public boolean hasNext() {
                 return nextIndex() < size;
             }
 

@@ -743,54 +758,74 @@
                 return i.previousIndex() - offset;
             }
 
             public void remove() {
                 i.remove();
-                SubList.this.modCount = l.modCount;
-                size--;
+                    updateSizeAndModCount(-1);
             }
 
             public void set(E e) {
                 i.set(e);
             }
 
             public void add(E e) {
                 i.add(e);
-                SubList.this.modCount = l.modCount;
-                size++;
+                    updateSizeAndModCount(1);
             }
         };
     }
 
     public List<E> subList(int fromIndex, int toIndex) {
+            subListRangeCheck(fromIndex, toIndex, size);
         return new SubList<>(this, fromIndex, toIndex);
     }
 
-    private void rangeCheck(int index) {
-        if (index < 0 || index >= size)
-            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
-    }
-
     private void rangeCheckForAdd(int index) {
         if (index < 0 || index > size)
             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
     }
 
     private String outOfBoundsMsg(int index) {
         return "Index: "+index+", Size: "+size;
     }
 
     private void checkForComodification() {
-        if (this.modCount != l.modCount)
+            if (root.modCount != this.modCount)
             throw new ConcurrentModificationException();
     }
-}
 
-class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
-    RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
-        super(list, fromIndex, toIndex);
+        private void updateSizeAndModCount(int sizeChange) {
+            SubList<E> slist = this;
+            do {
+                slist.size += sizeChange;
+                slist.modCount = root.modCount;
+                slist = slist.parent;
+            } while (slist != null);
+        }
+    }
+
+    private static class RandomAccessSubList<E>
+            extends SubList<E> implements RandomAccess {
+
+        /**
+         * Constructs a sublist of an arbitrary AbstractList, which is
+         * not a RandomAccessSubList itself.
+         */
+        RandomAccessSubList(AbstractList<E> root,
+                int fromIndex, int toIndex) {
+            super(root, fromIndex, toIndex);
+        }
+
+        /**
+         * Constructs a sublist of another RandomAccessSubList.
+         */
+        RandomAccessSubList(RandomAccessSubList<E> parent,
+                int fromIndex, int toIndex) {
+            super(parent, fromIndex, toIndex);
     }
 
     public List<E> subList(int fromIndex, int toIndex) {
+            subListRangeCheck(fromIndex, toIndex, size);
         return new RandomAccessSubList<>(this, fromIndex, toIndex);
     }
+    }
 }
< prev index next >