< prev index next >

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

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

*** 1004,1255 **** * @throws IndexOutOfBoundsException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ 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) { ! 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(); ! } ! ! 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; ! ! 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(); ! } ! ! public Spliterator<E> spliterator() { ! checkForComodification(); ! return new ArrayListSpliterator<>(ArrayList.this, offset, ! offset + this.size, this.modCount); ! } } @Override public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); --- 1004,1014 ---- * @throws IndexOutOfBoundsException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); ! return new ArraySubList<>(this, null, 0, fromIndex, toIndex); } @Override public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action);
*** 1468,1472 **** --- 1227,1465 ---- throw new ConcurrentModificationException(); } modCount++; } } + + class ArraySubList<E> extends AbstractList<E> implements RandomAccess { + final ArrayList<E> root; + final ArraySubList<E> parent; + final int offset; + int size; + + ArraySubList(ArrayList<E> root, ArraySubList<E> parent, + int offset, int fromIndex, int toIndex) { + this.root = root; + this.parent = parent; + this.offset = offset + fromIndex; + this.size = toIndex - fromIndex; + this.modCount = root.modCount; + } + + public E set(int index, E element) { + rangeCheck(index); + checkForComodification(); + E oldValue = root.elementData(offset + index); + root.elementData[offset + index] = element; + return oldValue; + } + + public E get(int index) { + rangeCheck(index); + checkForComodification(); + return root.elementData(offset + index); + } + + public int size() { + checkForComodification(); + return size; + } + + public void add(int index, E element) { + rangeCheckForAdd(index); + checkForComodification(); + root.add(offset + index, element); + updateSizeAndModCount(1); + } + + public E remove(int index) { + rangeCheck(index); + checkForComodification(); + E result = root.remove(offset + index); + updateSizeAndModCount(-1); + return result; + } + + protected void removeRange(int fromIndex, int toIndex) { + checkForComodification(); + root.removeRange(offset + fromIndex, offset + toIndex); + updateSizeAndModCount(fromIndex - toIndex); + } + + 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(); + root.addAll(offset + index, c); + updateSizeAndModCount(cSize); + return true; + } + + public Iterator<E> iterator() { + return listIterator(); + } + + public ListIterator<E> listIterator(int index) { + checkForComodification(); + rangeCheckForAdd(index); + + return new ListIterator<E>() { + int cursor = index; + int lastRet = -1; + int expectedModCount = root.modCount; + + public boolean hasNext() { + return cursor != ArraySubList.this.size; + } + + @SuppressWarnings("unchecked") + public E next() { + checkForComodification(); + int i = cursor; + if (i >= ArraySubList.this.size) + throw new NoSuchElementException(); + Object[] elementData = root.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 = root.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 = ArraySubList.this.size; + int i = cursor; + if (i >= size) { + return; + } + final Object[] elementData = root.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 { + ArraySubList.this.remove(lastRet); + cursor = lastRet; + lastRet = -1; + expectedModCount = root.modCount; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + public void set(E e) { + if (lastRet < 0) + throw new IllegalStateException(); + checkForComodification(); + + try { + root.set(offset + lastRet, e); + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + public void add(E e) { + checkForComodification(); + + try { + int i = cursor; + ArraySubList.this.add(i, e); + cursor = i + 1; + lastRet = -1; + expectedModCount = root.modCount; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + final void checkForComodification() { + if (root.modCount != expectedModCount) + throw new ConcurrentModificationException(); + } + }; + } + + public List<E> subList(int fromIndex, int toIndex) { + subListRangeCheck(fromIndex, toIndex, size); + return new ArraySubList<>(root, this, offset, 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 (root.modCount != modCount) + throw new ConcurrentModificationException(); + } + + private void updateSizeAndModCount(int sizeChange) { + ArraySubList<E> slist = this; + do { + slist.size += sizeChange; + slist.modCount = root.modCount; + slist = slist.parent; + } while (slist != null); + } + + public Spliterator<E> spliterator() { + checkForComodification(); + return new ArrayList.ArrayListSpliterator<>(root, offset, + offset + size, modCount); + } + } +
< prev index next >