--- jsr166/src/main/java/util/Vector.java 2005/11/26 03:12:10 1.2
+++ jsr166/src/main/java/util/Vector.java 2006/05/28 23:36:29 1.13
@@ -1,34 +1,29 @@
/*
* %W% %E%
*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util;
-import java.util.*; // for javadoc (till 6280605 is fixed)
/**
* The Vector
class implements a growable array of
* objects. Like an array, it contains components that can be
* accessed using an integer index. However, the size of a
* Vector
can grow or shrink as needed to accommodate
- * adding and removing items after the Vector
has been created.
+ * adding and removing items after the Vector
has been created.
*
- * Each vector tries to optimize storage management by maintaining a
+ *
Each vector tries to optimize storage management by maintaining a
* capacity
and a capacityIncrement
. The
* capacity
is always at least as large as the vector
* size; it is usually larger because as components are added to the
* vector, the vector's storage increases in chunks the size of
* capacityIncrement
. An application can increase the
* capacity of a vector before inserting a large number of
- * components; this reduces the amount of incremental reallocation.
+ * components; this reduces the amount of incremental reallocation.
*
- * As of the Java 2 platform v1.2, this class has been retrofitted to
- * implement List, so that it becomes a part of Java's collection framework.
- * Unlike the new collection implementations, Vector is synchronized.
- *
- * The Iterators returned by Vector's iterator and listIterator
+ *
The Iterators returned by Vector's iterator and listIterator
* methods are fail-fast: if the Vector is structurally modified
* at any time after the Iterator is created, in any way except through the
* Iterator's own remove or add methods, the Iterator will throw a
@@ -44,11 +39,13 @@ import java.util.*; // for javadoc (till
* throw ConcurrentModificationException on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: the fail-fast behavior of iterators
- * should be used only to detect bugs.
+ * should be used only to detect bugs.
*
- * This class is a member of the
- *
- * Java Collections Framework.
+ *
As of the Java 2 platform v1.2, this class was retrofitted to
+ * implement the {@link List} interface, making it a member of the
+ * Java
+ * Collections Framework. Unlike the new collection
+ * implementations, {@code Vector} is synchronized.
*
* @author Lee Boynton
* @author Jonathan Payne
@@ -147,13 +144,11 @@ public class Vector
* @since 1.2
*/
public Vector(Collection extends E> c) {
- Object[] a = c.toArray();
- elementCount = a.length;
- // If c.toArray incorrectly doesn't return Object[], copy it.
- if (a.getClass() == Object[].class)
- elementData = a;
- else
- elementData = Arrays.copyOf(a, a.length, Object[].class);
+ elementData = c.toArray();
+ elementCount = elementData.length;
+ // c.toArray might (incorrectly) not return Object[] (see 6260652)
+ if (elementData.getClass() != Object[].class)
+ elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
/**
@@ -957,49 +952,10 @@ public class Vector
}
/**
- * Returns a view of the portion of this List between fromIndex,
- * inclusive, and toIndex, exclusive. (If fromIndex and toIndex are
- * equal, the returned List is empty.) The returned List is backed by this
- * List, so changes in the returned List are reflected in this List, and
- * vice-versa. The returned List supports all of the optional List
- * operations supported by this List.
- *
- * This method eliminates the need for explicit range operations (of
- * the sort that commonly exist for arrays). Any operation that expects
- * a List can be used as a range operation by operating on a subList view
- * instead of a whole List. For example, the following idiom
- * removes a range of elements from a List:
- *
- * list.subList(from, to).clear();
- *
- * Similar idioms may be constructed for indexOf and lastIndexOf,
- * and all of the algorithms in the Collections class can be applied to
- * a subList.
- *
- * The semantics of the List returned by this method become undefined if
- * the backing list (i.e., this List) is structurally modified in
- * any way other than via the returned List. (Structural modifications are
- * those that change the size of the List, or otherwise perturb it in such
- * a fashion that iterations in progress may yield incorrect results.)
- *
- * @param fromIndex low endpoint (inclusive) of the subList
- * @param toIndex high endpoint (exclusive) of the subList
- * @return a view of the specified range within this List
- * @throws IndexOutOfBoundsException endpoint index value out of range
- * (fromIndex < 0 || toIndex > size)
- * @throws IllegalArgumentException endpoint indices out of order
- * (fromIndex > toIndex)
- */
- public synchronized List subList(int fromIndex, int toIndex) {
- return Collections.synchronizedList(super.subList(fromIndex, toIndex),
- this);
- }
-
- /**
* Removes from this List all of the elements whose index is between
* fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
* elements to the left (reduces their index).
- * This call shortens the ArrayList by (toIndex - fromIndex) elements. (If
+ * This call shortens the Vector by (toIndex - fromIndex) elements. (If
* toIndex==fromIndex, this operation has no effect.)
*
* @param fromIndex index of first element to be removed
@@ -1031,28 +987,34 @@ public class Vector
/**
* Returns a list-iterator of the elements in this list (in proper
* sequence), starting at the specified position in the list.
- * Obeys the general contract of List.listIterator(int).
+ * Obeys the general contract of {@link List#listIterator(int)}.
*
- * The list-iterator is fail-fast: if the list is structurally
+ *
The list-iterator is fail-fast: if the list is structurally
* modified at any time after the Iterator is created, in any way except
- * through the list-iterator's own remove or add
+ * through the list-iterator's own {@code remove} or {@code add}
* methods, the list-iterator will throw a
- * ConcurrentModificationException. Thus, in the face of
+ * {@code ConcurrentModificationException}. Thus, in the face of
* concurrent modification, the iterator fails quickly and cleanly, rather
* than risking arbitrary, non-deterministic behavior at an undetermined
* time in the future.
*
* @param index index of the first element to be returned from the
- * list-iterator (by a call to next)
- * @return a ListIterator of the elements in this list (in proper
+ * list-iterator (by a call to {@link ListIterator#next})
+ * @return a list-iterator of the elements in this list (in proper
* sequence), starting at the specified position in the list
* @throws IndexOutOfBoundsException {@inheritDoc}
- * @see List#listIterator(int)
*/
public synchronized ListIterator listIterator(int index) {
if (index < 0 || index > elementCount)
throw new IndexOutOfBoundsException("Index: "+index);
- return new VectorIterator(index);
+ return new VectorIterator(index, elementCount);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized ListIterator listIterator() {
+ return new VectorIterator(0, elementCount);
}
/**
@@ -1061,26 +1023,45 @@ public class Vector
* @return an iterator over the elements in this list in proper sequence
*/
public synchronized Iterator iterator() {
- return new VectorIterator(0);
+ return new VectorIterator(0, elementCount);
}
/**
- * A streamlined version of AbstractList.Itr.
+ * Helper method to access array elements under synchronization by
+ * iterators. The caller performs index check with respect to
+ * expected bounds, so errors accessing the element are reported
+ * as ConcurrentModificationExceptions.
*/
- final class VectorIterator implements ListIterator {
- int cursor; // index of next element to return;
- int lastRet; // index of last element, or -1 if no such
- int expectedModCount; // to check for CME
+ final synchronized Object iteratorGet(int index, int expectedModCount) {
+ if (modCount == expectedModCount) {
+ try {
+ return elementData[index];
+ } catch(IndexOutOfBoundsException fallThrough) {
+ }
+ }
+ throw new ConcurrentModificationException();
+ }
- VectorIterator(int index) {
- cursor = index;
- lastRet = -1;
- expectedModCount = modCount;
+ /**
+ * Streamlined specialization of AbstractList version of iterator.
+ * Locally perfroms bounds checks, but relies on outer Vector
+ * to access elements under synchronization.
+ */
+ private final class VectorIterator implements ListIterator {
+ int cursor; // Index of next element to return;
+ int fence; // Upper bound on cursor (cache of size())
+ int lastRet; // Index of last element, or -1 if no such
+ int expectedModCount; // To check for CME
+
+ VectorIterator(int index, int fence) {
+ this.cursor = index;
+ this.fence = fence;
+ this.lastRet = -1;
+ this.expectedModCount = Vector.this.modCount;
}
public boolean hasNext() {
- // Racy but within spec and backwards-compatible
- return cursor < elementCount;
+ return cursor < fence;
}
public boolean hasPrevious() {
@@ -1096,80 +1077,382 @@ public class Vector
}
public E next() {
- synchronized(Vector.this) {
- if (expectedModCount == modCount) {
- int i = cursor;
- if (i < elementCount) {
- try {
- E e = (E)elementData[i];
- lastRet = i;
- cursor = i + 1;
- return e;
- } catch (IndexOutOfBoundsException fallthrough) {
- }
- }
- }
- // Prefer reporting CME if applicable on failures
- if (expectedModCount == modCount)
- throw new NoSuchElementException();
- throw new ConcurrentModificationException();
- }
+ int i = cursor;
+ if (i >= fence)
+ throw new NoSuchElementException();
+ Object next = Vector.this.iteratorGet(i, expectedModCount);
+ lastRet = i;
+ cursor = i + 1;
+ return (E)next;
}
public E previous() {
- synchronized(Vector.this) {
- if (expectedModCount == modCount) {
- int i = cursor - 1;
- if (i < elementCount) {
- try {
- E e = (E)elementData[i];
- lastRet = i;
- cursor = i;
- return e;
- } catch (IndexOutOfBoundsException fallthrough) {
- }
- }
- }
- if (expectedModCount == modCount)
- throw new NoSuchElementException();
- throw new ConcurrentModificationException();
- }
+ int i = cursor - 1;
+ if (i < 0)
+ throw new NoSuchElementException();
+ Object prev = Vector.this.iteratorGet(i, expectedModCount);
+ lastRet = i;
+ cursor = i;
+ return (E)prev;
}
- public void remove() {
+ public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
- synchronized(Vector.this) {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- Vector.this.remove(lastRet);
- if (lastRet < cursor)
- cursor--;
- lastRet = -1;
- expectedModCount = modCount;
- }
+ if (Vector.this.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ try {
+ Vector.this.set(lastRet, e);
+ expectedModCount = Vector.this.modCount;
+ } catch (IndexOutOfBoundsException ex) {
+ throw new ConcurrentModificationException();
+ }
}
- public void set(E e) {
- if (lastRet < 0)
+ public void remove() {
+ int i = lastRet;
+ if (i < 0)
throw new IllegalStateException();
- synchronized(Vector.this) {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- Vector.this.set(lastRet, e);
- expectedModCount = modCount;
- }
+ if (Vector.this.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ try {
+ Vector.this.remove(i);
+ if (i < cursor)
+ cursor--;
+ lastRet = -1;
+ fence = Vector.this.size();
+ expectedModCount = Vector.this.modCount;
+ } catch (IndexOutOfBoundsException ex) {
+ throw new ConcurrentModificationException();
+ }
}
public void add(E e) {
- synchronized(Vector.this) {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- Vector.this.add(cursor++, e);
+ if (Vector.this.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ try {
+ int i = cursor;
+ Vector.this.add(i, e);
+ cursor = i + 1;
lastRet = -1;
- expectedModCount = modCount;
- }
+ fence = Vector.this.size();
+ expectedModCount = Vector.this.modCount;
+ } catch (IndexOutOfBoundsException ex) {
+ throw new ConcurrentModificationException();
+ }
}
}
+ /**
+ * Returns a view of the portion of this List between fromIndex,
+ * inclusive, and toIndex, exclusive. (If fromIndex and toIndex are
+ * equal, the returned List is empty.) The returned List is backed by this
+ * List, so changes in the returned List are reflected in this List, and
+ * vice-versa. The returned List supports all of the optional List
+ * operations supported by this List.
+ *
+ * This method eliminates the need for explicit range operations (of
+ * the sort that commonly exist for arrays). Any operation that expects
+ * a List can be used as a range operation by operating on a subList view
+ * instead of a whole List. For example, the following idiom
+ * removes a range of elements from a List:
+ *
+ * list.subList(from, to).clear();
+ *
+ * Similar idioms may be constructed for indexOf and lastIndexOf,
+ * and all of the algorithms in the Collections class can be applied to
+ * a subList.
+ *
+ * The semantics of the List returned by this method become undefined if
+ * the backing list (i.e., this List) is structurally modified in
+ * any way other than via the returned List. (Structural modifications are
+ * those that change the size of the List, or otherwise perturb it in such
+ * a fashion that iterations in progress may yield incorrect results.)
+ *
+ * @param fromIndex low endpoint (inclusive) of the subList
+ * @param toIndex high endpoint (exclusive) of the subList
+ * @return a view of the specified range within this List
+ * @throws IndexOutOfBoundsException endpoint index value out of range
+ * (fromIndex < 0 || toIndex > size)
+ * @throws IllegalArgumentException endpoint indices out of order
+ * (fromIndex > toIndex)
+ */
+ public synchronized List subList(int fromIndex, int toIndex) {
+ return new VectorSubList(this, this, fromIndex, fromIndex, toIndex);
+ }
+
+ /**
+ * This class specializes the AbstractList version of SubList to
+ * avoid the double-indirection penalty that would arise using a
+ * synchronized wrapper, as well as to avoid some unnecessary
+ * checks in sublist iterators.
+ */
+ private static final class VectorSubList extends AbstractList implements RandomAccess {
+ final Vector base; // base list
+ final AbstractList parent; // Creating list
+ final int baseOffset; // index wrt Vector
+ final int parentOffset; // index wrt parent
+ int length; // length of sublist
+
+ VectorSubList(Vector base, AbstractList parent, int baseOffset,
+ int fromIndex, int toIndex) {
+ if (fromIndex < 0)
+ throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
+ if (toIndex > parent.size())
+ throw new IndexOutOfBoundsException("toIndex = " + toIndex);
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException("fromIndex(" + fromIndex +
+ ") > toIndex(" + toIndex + ")");
+
+ this.base = base;
+ this.parent = parent;
+ this.baseOffset = baseOffset;
+ this.parentOffset = fromIndex;
+ this.length = toIndex - fromIndex;
+ modCount = base.modCount;
+ }
+
+ /**
+ * Returns an IndexOutOfBoundsException with nicer message
+ */
+ private IndexOutOfBoundsException indexError(int index) {
+ return new IndexOutOfBoundsException("Index: " + index +
+ ", Size: " + length);
+ }
+
+ public E set(int index, E element) {
+ synchronized(base) {
+ if (index < 0 || index >= length)
+ throw indexError(index);
+ if (base.modCount != modCount)
+ throw new ConcurrentModificationException();
+ return base.set(index + baseOffset, element);
+ }
+ }
+
+ public E get(int index) {
+ synchronized(base) {
+ if (index < 0 || index >= length)
+ throw indexError(index);
+ if (base.modCount != modCount)
+ throw new ConcurrentModificationException();
+ return base.get(index + baseOffset);
+ }
+ }
+
+ public int size() {
+ synchronized(base) {
+ if (base.modCount != modCount)
+ throw new ConcurrentModificationException();
+ return length;
+ }
+ }
+
+ public void add(int index, E element) {
+ synchronized(base) {
+ if (index < 0 || index > length)
+ throw indexError(index);
+ if (base.modCount != modCount)
+ throw new ConcurrentModificationException();
+ parent.add(index + parentOffset, element);
+ length++;
+ modCount = base.modCount;
+ }
+ }
+
+ public E remove(int index) {
+ synchronized(base) {
+ if (index < 0 || index >= length)
+ throw indexError(index);
+ if (base.modCount != modCount)
+ throw new ConcurrentModificationException();
+ E result = parent.remove(index + parentOffset);
+ length--;
+ modCount = base.modCount;
+ return result;
+ }
+ }
+
+ protected void removeRange(int fromIndex, int toIndex) {
+ synchronized(base) {
+ if (base.modCount != modCount)
+ throw new ConcurrentModificationException();
+ parent.removeRange(fromIndex + parentOffset,
+ toIndex + parentOffset);
+ length -= (toIndex-fromIndex);
+ modCount = base.modCount;
+ }
+ }
+
+ public boolean addAll(Collection extends E> c) {
+ return addAll(length, c);
+ }
+
+ public boolean addAll(int index, Collection extends E> c) {
+ synchronized(base) {
+ if (index < 0 || index > length)
+ throw indexError(index);
+ int cSize = c.size();
+ if (cSize==0)
+ return false;
+
+ if (base.modCount != modCount)
+ throw new ConcurrentModificationException();
+ parent.addAll(parentOffset + index, c);
+ modCount = base.modCount;
+ length += cSize;
+ return true;
+ }
+ }
+
+ public boolean equals(Object o) {
+ synchronized(base) {return super.equals(o);}
+ }
+
+ public int hashCode() {
+ synchronized(base) {return super.hashCode();}
+ }
+
+ public int indexOf(Object o) {
+ synchronized(base) {return super.indexOf(o);}
+ }
+
+ public int lastIndexOf(Object o) {
+ synchronized(base) {return super.lastIndexOf(o);}
+ }
+
+ public List subList(int fromIndex, int toIndex) {
+ return new VectorSubList(base, this, fromIndex + baseOffset,
+ fromIndex, toIndex);
+ }
+
+ public Iterator iterator() {
+ synchronized(base) {
+ return new VectorSubListIterator(this, 0);
+ }
+ }
+
+ public synchronized ListIterator listIterator() {
+ synchronized(base) {
+ return new VectorSubListIterator(this, 0);
+ }
+ }
+
+ public ListIterator listIterator(int index) {
+ synchronized(base) {
+ if (index < 0 || index > length)
+ throw indexError(index);
+ return new VectorSubListIterator(this, index);
+ }
+ }
+
+ /**
+ * Same idea as VectorIterator, except routing structural
+ * change operations through the sublist.
+ */
+ private static final class VectorSubListIterator implements ListIterator {
+ final Vector base; // base list
+ final VectorSubList outer; // Sublist creating this iteraor
+ final int offset; // cursor offset wrt base
+ int cursor; // Current index
+ int fence; // Upper bound on cursor
+ int lastRet; // Index of returned element, or -1
+ int expectedModCount; // Expected modCount of base Vector
+
+ VectorSubListIterator(VectorSubList list, int index) {
+ this.lastRet = -1;
+ this.cursor = index;
+ this.outer = list;
+ this.offset = list.baseOffset;
+ this.fence = list.length;
+ this.base = list.base;
+ this.expectedModCount = base.modCount;
+ }
+
+ public boolean hasNext() {
+ return cursor < fence;
+ }
+
+ public boolean hasPrevious() {
+ return cursor > 0;
+ }
+
+ public int nextIndex() {
+ return cursor;
+ }
+
+ public int previousIndex() {
+ return cursor - 1;
+ }
+
+ public E next() {
+ int i = cursor;
+ if (cursor >= fence)
+ throw new NoSuchElementException();
+ Object next = base.iteratorGet(i + offset, expectedModCount);
+ lastRet = i;
+ cursor = i + 1;
+ return (E)next;
+ }
+
+ public E previous() {
+ int i = cursor - 1;
+ if (i < 0)
+ throw new NoSuchElementException();
+ Object prev = base.iteratorGet(i + offset, expectedModCount);
+ lastRet = i;
+ cursor = i;
+ return (E)prev;
+ }
+
+ public void set(E e) {
+ if (lastRet < 0)
+ throw new IllegalStateException();
+ if (base.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ try {
+ outer.set(lastRet, e);
+ expectedModCount = base.modCount;
+ } catch (IndexOutOfBoundsException ex) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ public void remove() {
+ int i = lastRet;
+ if (i < 0)
+ throw new IllegalStateException();
+ if (base.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ try {
+ outer.remove(i);
+ if (i < cursor)
+ cursor--;
+ lastRet = -1;
+ fence = outer.length;
+ expectedModCount = base.modCount;
+ } catch (IndexOutOfBoundsException ex) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ public void add(E e) {
+ if (base.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ try {
+ int i = cursor;
+ outer.add(i, e);
+ cursor = i + 1;
+ lastRet = -1;
+ fence = outer.length;
+ expectedModCount = base.modCount;
+ } catch (IndexOutOfBoundsException ex) {
+ throw new ConcurrentModificationException();
+ }
+ }
+ }
+ }
}
+
+
+