Home | History | Annotate | Download | only in util
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.util;
     19 
     20 import java.io.IOException;
     21 import java.io.ObjectOutputStream;
     22 import java.io.Serializable;
     23 import java.lang.reflect.Array;
     24 
     25 /**
     26  * Vector is an implementation of {@link List}, backed by an array and synchronized.
     27  * All optional operations including adding, removing, and replacing elements are supported.
     28  *
     29  * <p>All elements are permitted, including null.
     30  *
     31  * <p>This class is equivalent to {@link ArrayList} with synchronized operations. This has a
     32  * performance cost, and the synchronization is not necessarily meaningful to your application:
     33  * synchronizing each call to {@code get}, for example, is not equivalent to synchronizing on the
     34  * list and iterating over it (which is probably what you intended). If you do need very highly
     35  * concurrent access, you should also consider {@link java.util.concurrent.CopyOnWriteArrayList}.
     36  *
     37  * @param <E> The element type of this list.
     38  */
     39 public class Vector<E> extends AbstractList<E> implements List<E>,
     40         RandomAccess, Cloneable, Serializable {
     41 
     42     private static final long serialVersionUID = -2767605614048989439L;
     43 
     44     /**
     45      * The number of elements or the size of the vector.
     46      */
     47     protected int elementCount;
     48 
     49     /**
     50      * The elements of the vector.
     51      */
     52     protected Object[] elementData;
     53 
     54     /**
     55      * How many elements should be added to the vector when it is detected that
     56      * it needs to grow to accommodate extra entries. If this value is zero or
     57      * negative the size will be doubled if an increase is needed.
     58      */
     59     protected int capacityIncrement;
     60 
     61     private static final int DEFAULT_SIZE = 10;
     62 
     63     /**
     64      * Constructs a new vector using the default capacity.
     65      */
     66     public Vector() {
     67         this(DEFAULT_SIZE, 0);
     68     }
     69 
     70     /**
     71      * Constructs a new vector using the specified capacity.
     72      *
     73      * @param capacity
     74      *            the initial capacity of the new vector.
     75      * @throws IllegalArgumentException
     76      *             if {@code capacity} is negative.
     77      */
     78     public Vector(int capacity) {
     79         this(capacity, 0);
     80     }
     81 
     82     /**
     83      * Constructs a new vector using the specified capacity and capacity
     84      * increment.
     85      *
     86      * @param capacity
     87      *            the initial capacity of the new vector.
     88      * @param capacityIncrement
     89      *            the amount to increase the capacity when this vector is full.
     90      * @throws IllegalArgumentException
     91      *             if {@code capacity} is negative.
     92      */
     93     public Vector(int capacity, int capacityIncrement) {
     94         if (capacity < 0) {
     95             throw new IllegalArgumentException();
     96         }
     97         elementData = newElementArray(capacity);
     98         elementCount = 0;
     99         this.capacityIncrement = capacityIncrement;
    100     }
    101 
    102     /**
    103      * Constructs a new instance of {@code Vector} containing the elements in
    104      * {@code collection}. The order of the elements in the new {@code Vector}
    105      * is dependent on the iteration order of the seed collection.
    106      *
    107      * @param collection
    108      *            the collection of elements to add.
    109      */
    110     public Vector(Collection<? extends E> collection) {
    111         this(collection.size(), 0);
    112         Iterator<? extends E> it = collection.iterator();
    113         while (it.hasNext()) {
    114             elementData[elementCount++] = it.next();
    115         }
    116     }
    117 
    118     @SuppressWarnings("unchecked")
    119     private E[] newElementArray(int size) {
    120         return (E[]) new Object[size];
    121     }
    122 
    123     /**
    124      * Adds the specified object into this vector at the specified location. The
    125      * object is inserted before any element with the same or a higher index
    126      * increasing their index by 1. If the location is equal to the size of this
    127      * vector, the object is added at the end.
    128      *
    129      * @param location
    130      *            the index at which to insert the element.
    131      * @param object
    132      *            the object to insert in this vector.
    133      * @throws ArrayIndexOutOfBoundsException
    134      *                if {@code location < 0 || location > size()}.
    135      * @see #addElement
    136      * @see #size
    137      */
    138     @Override
    139     public void add(int location, E object) {
    140         insertElementAt(object, location);
    141     }
    142 
    143     /**
    144      * Adds the specified object at the end of this vector.
    145      *
    146      * @param object
    147      *            the object to add to the vector.
    148      * @return {@code true}
    149      */
    150     @Override
    151     public synchronized boolean add(E object) {
    152         if (elementCount == elementData.length) {
    153             growByOne();
    154         }
    155         elementData[elementCount++] = object;
    156         modCount++;
    157         return true;
    158     }
    159 
    160     /**
    161      * Inserts the objects in the specified collection at the specified location
    162      * in this vector. The objects are inserted in the order in which they are
    163      * returned from the Collection iterator. The elements with an index equal
    164      * or higher than {@code location} have their index increased by the size of
    165      * the added collection.
    166      *
    167      * @param location
    168      *            the location to insert the objects.
    169      * @param collection
    170      *            the collection of objects.
    171      * @return {@code true} if this vector is modified, {@code false} otherwise.
    172      * @throws ArrayIndexOutOfBoundsException
    173      *                if {@code location < 0} or {@code location > size()}.
    174      */
    175     @Override
    176     public synchronized boolean addAll(int location,
    177             Collection<? extends E> collection) {
    178         if (0 <= location && location <= elementCount) {
    179             int size = collection.size();
    180             if (size == 0) {
    181                 return false;
    182             }
    183             int required = size - (elementData.length - elementCount);
    184             if (required > 0) {
    185                 growBy(required);
    186             }
    187             int count = elementCount - location;
    188             if (count > 0) {
    189                 System.arraycopy(elementData, location, elementData, location
    190                         + size, count);
    191             }
    192             Iterator<? extends E> it = collection.iterator();
    193             while (it.hasNext()) {
    194                 elementData[location++] = it.next();
    195             }
    196             elementCount += size;
    197             modCount++;
    198             return true;
    199         }
    200         throw new ArrayIndexOutOfBoundsException(location);
    201     }
    202 
    203     /**
    204      * Adds the objects in the specified collection to the end of this vector.
    205      *
    206      * @param collection
    207      *            the collection of objects.
    208      * @return {@code true} if this vector is modified, {@code false} otherwise.
    209      */
    210     @Override
    211     public synchronized boolean addAll(Collection<? extends E> collection) {
    212         return addAll(elementCount, collection);
    213     }
    214 
    215     /**
    216      * Adds the specified object at the end of this vector.
    217      *
    218      * @param object
    219      *            the object to add to the vector.
    220      */
    221     public synchronized void addElement(E object) {
    222         if (elementCount == elementData.length) {
    223             growByOne();
    224         }
    225         elementData[elementCount++] = object;
    226         modCount++;
    227     }
    228 
    229     /**
    230      * Returns the number of elements this vector can hold without growing.
    231      *
    232      * @return the capacity of this vector.
    233      * @see #ensureCapacity
    234      * @see #size
    235      */
    236     public synchronized int capacity() {
    237         return elementData.length;
    238     }
    239 
    240     /**
    241      * Removes all elements from this vector, leaving it empty.
    242      *
    243      * @see #isEmpty
    244      * @see #size
    245      */
    246     @Override
    247     public void clear() {
    248         removeAllElements();
    249     }
    250 
    251     /**
    252      * Returns a new vector with the same elements, size, capacity and capacity
    253      * increment as this vector.
    254      *
    255      * @return a shallow copy of this vector.
    256      * @see java.lang.Cloneable
    257      */
    258     @Override
    259     @SuppressWarnings("unchecked")
    260     public synchronized Object clone() {
    261         try {
    262             Vector<E> vector = (Vector<E>) super.clone();
    263             vector.elementData = elementData.clone();
    264             return vector;
    265         } catch (CloneNotSupportedException e) {
    266             throw new AssertionError(e); // android-changed
    267         }
    268     }
    269 
    270     /**
    271      * Searches this vector for the specified object.
    272      *
    273      * @param object
    274      *            the object to look for in this vector.
    275      * @return {@code true} if object is an element of this vector,
    276      *         {@code false} otherwise.
    277      * @see #indexOf(Object)
    278      * @see #indexOf(Object, int)
    279      * @see java.lang.Object#equals
    280      */
    281     @Override
    282     public boolean contains(Object object) {
    283         return indexOf(object, 0) != -1;
    284     }
    285 
    286     /**
    287      * Searches this vector for all objects in the specified collection.
    288      *
    289      * @param collection
    290      *            the collection of objects.
    291      * @return {@code true} if all objects in the specified collection are
    292      *         elements of this vector, {@code false} otherwise.
    293      */
    294     @Override
    295     public synchronized boolean containsAll(Collection<?> collection) {
    296         return super.containsAll(collection);
    297     }
    298 
    299     /**
    300      * Attempts to copy elements contained by this {@code Vector} into the
    301      * corresponding elements of the supplied {@code Object} array.
    302      *
    303      * @param elements
    304      *            the {@code Object} array into which the elements of this
    305      *            vector are copied.
    306      * @throws IndexOutOfBoundsException
    307      *             if {@code elements} is not big enough.
    308      * @see #clone
    309      */
    310     public synchronized void copyInto(Object[] elements) {
    311         System.arraycopy(elementData, 0, elements, 0, elementCount);
    312     }
    313 
    314     /**
    315      * Returns the element at the specified location in this vector.
    316      *
    317      * @param location
    318      *            the index of the element to return in this vector.
    319      * @return the element at the specified location.
    320      * @throws ArrayIndexOutOfBoundsException
    321      *                if {@code location < 0 || location >= size()}.
    322      * @see #size
    323      */
    324     @SuppressWarnings("unchecked")
    325     public synchronized E elementAt(int location) {
    326         if (location < elementCount) {
    327             return (E) elementData[location];
    328         }
    329         throw new ArrayIndexOutOfBoundsException(location);
    330     }
    331 
    332     /**
    333      * Returns an enumeration on the elements of this vector. The results of the
    334      * enumeration may be affected if the contents of this vector is modified.
    335      *
    336      * @return an enumeration of the elements of this vector.
    337      * @see #elementAt
    338      * @see Enumeration
    339      */
    340     public Enumeration<E> elements() {
    341         return new Enumeration<E>() {
    342             int pos = 0;
    343 
    344             public boolean hasMoreElements() {
    345                 return pos < elementCount;
    346             }
    347 
    348             @SuppressWarnings("unchecked")
    349             public E nextElement() {
    350                 synchronized (Vector.this) {
    351                     if (pos < elementCount) {
    352                         return (E) elementData[pos++];
    353                     }
    354                 }
    355                 throw new NoSuchElementException();
    356             }
    357         };
    358     }
    359 
    360     /**
    361      * Ensures that this vector can hold the specified number of elements
    362      * without growing.
    363      *
    364      * @param minimumCapacity
    365      *            the minimum number of elements that this vector will hold
    366      *            before growing.
    367      * @see #capacity
    368      */
    369     public synchronized void ensureCapacity(int minimumCapacity) {
    370         if (elementData.length < minimumCapacity) {
    371             int next = (capacityIncrement <= 0 ? elementData.length
    372                     : capacityIncrement)
    373                     + elementData.length;
    374             grow(minimumCapacity > next ? minimumCapacity : next);
    375         }
    376     }
    377 
    378     /**
    379      * Compares the specified object to this vector and returns if they are
    380      * equal. The object must be a List which contains the same objects in the
    381      * same order.
    382      *
    383      * @param object
    384      *            the object to compare with this object
    385      * @return {@code true} if the specified object is equal to this vector,
    386      *         {@code false} otherwise.
    387      * @see #hashCode
    388      */
    389     @Override
    390     public synchronized boolean equals(Object object) {
    391         if (this == object) {
    392             return true;
    393         }
    394         if (object instanceof List) {
    395             List<?> list = (List<?>) object;
    396             if (list.size() != elementCount) {
    397                 return false;
    398             }
    399 
    400             int index = 0;
    401             Iterator<?> it = list.iterator();
    402             while (it.hasNext()) {
    403                 Object e1 = elementData[index++], e2 = it.next();
    404                 if (!(e1 == null ? e2 == null : e1.equals(e2))) {
    405                     return false;
    406                 }
    407             }
    408             return true;
    409         }
    410         return false;
    411     }
    412 
    413     /**
    414      * Returns the first element in this vector.
    415      *
    416      * @return the element at the first position.
    417      * @throws NoSuchElementException
    418      *                if this vector is empty.
    419      * @see #elementAt
    420      * @see #lastElement
    421      * @see #size
    422      */
    423     @SuppressWarnings("unchecked")
    424     public synchronized E firstElement() {
    425         if (elementCount > 0) {
    426             return (E) elementData[0];
    427         }
    428         throw new NoSuchElementException();
    429     }
    430 
    431     /**
    432      * Returns the element at the specified location in this vector.
    433      *
    434      * @param location
    435      *            the index of the element to return in this vector.
    436      * @return the element at the specified location.
    437      * @throws ArrayIndexOutOfBoundsException
    438      *                if {@code location < 0 || location >= size()}.
    439      * @see #size
    440      */
    441     @Override
    442     public E get(int location) {
    443         return elementAt(location);
    444     }
    445 
    446     private void grow(int newCapacity) {
    447         E[] newData = newElementArray(newCapacity);
    448         // Assumes elementCount is <= newCapacity
    449         assert elementCount <= newCapacity;
    450         System.arraycopy(elementData, 0, newData, 0, elementCount);
    451         elementData = newData;
    452     }
    453 
    454     /**
    455      * JIT optimization
    456      */
    457     private void growByOne() {
    458         int adding = 0;
    459         if (capacityIncrement <= 0) {
    460             if ((adding = elementData.length) == 0) {
    461                 adding = 1;
    462             }
    463         } else {
    464             adding = capacityIncrement;
    465         }
    466 
    467         E[] newData = newElementArray(elementData.length + adding);
    468         System.arraycopy(elementData, 0, newData, 0, elementCount);
    469         elementData = newData;
    470     }
    471 
    472     private void growBy(int required) {
    473         int adding = 0;
    474         if (capacityIncrement <= 0) {
    475             if ((adding = elementData.length) == 0) {
    476                 adding = required;
    477             }
    478             while (adding < required) {
    479                 adding += adding;
    480             }
    481         } else {
    482             adding = (required / capacityIncrement) * capacityIncrement;
    483             if (adding < required) {
    484                 adding += capacityIncrement;
    485             }
    486         }
    487         E[] newData = newElementArray(elementData.length + adding);
    488         System.arraycopy(elementData, 0, newData, 0, elementCount);
    489         elementData = newData;
    490     }
    491 
    492     /**
    493      * Returns an integer hash code for the receiver. Objects which are equal
    494      * return the same value for this method.
    495      *
    496      * @return the receiver's hash.
    497      * @see #equals
    498      */
    499     @Override
    500     public synchronized int hashCode() {
    501         int result = 1;
    502         for (int i = 0; i < elementCount; i++) {
    503             result = (31 * result)
    504                     + (elementData[i] == null ? 0 : elementData[i].hashCode());
    505         }
    506         return result;
    507     }
    508 
    509     /**
    510      * Searches in this vector for the index of the specified object. The search
    511      * for the object starts at the beginning and moves towards the end of this
    512      * vector.
    513      *
    514      * @param object
    515      *            the object to find in this vector.
    516      * @return the index in this vector of the specified element, -1 if the
    517      *         element isn't found.
    518      * @see #contains
    519      * @see #lastIndexOf(Object)
    520      * @see #lastIndexOf(Object, int)
    521      */
    522     @Override
    523     public int indexOf(Object object) {
    524         return indexOf(object, 0);
    525     }
    526 
    527     /**
    528      * Searches in this vector for the index of the specified object. The search
    529      * for the object starts at the specified location and moves towards the end
    530      * of this vector.
    531      *
    532      * @param object
    533      *            the object to find in this vector.
    534      * @param location
    535      *            the index at which to start searching.
    536      * @return the index in this vector of the specified element, -1 if the
    537      *         element isn't found.
    538      * @throws ArrayIndexOutOfBoundsException
    539      *                if {@code location < 0}.
    540      * @see #contains
    541      * @see #lastIndexOf(Object)
    542      * @see #lastIndexOf(Object, int)
    543      */
    544     public synchronized int indexOf(Object object, int location) {
    545         if (object != null) {
    546             for (int i = location; i < elementCount; i++) {
    547                 if (object.equals(elementData[i])) {
    548                     return i;
    549                 }
    550             }
    551         } else {
    552             for (int i = location; i < elementCount; i++) {
    553                 if (elementData[i] == null) {
    554                     return i;
    555                 }
    556             }
    557         }
    558         return -1;
    559     }
    560 
    561     /**
    562      * Inserts the specified object into this vector at the specified location.
    563      * This object is inserted before any previous element at the specified
    564      * location. All elements with an index equal or greater than
    565      * {@code location} have their index increased by 1. If the location is
    566      * equal to the size of this vector, the object is added at the end.
    567      *
    568      * @param object
    569      *            the object to insert in this vector.
    570      * @param location
    571      *            the index at which to insert the element.
    572      * @throws ArrayIndexOutOfBoundsException
    573      *                if {@code location < 0 || location > size()}.
    574      * @see #addElement
    575      * @see #size
    576      */
    577     public synchronized void insertElementAt(E object, int location) {
    578         if (0 <= location && location <= elementCount) {
    579             if (elementCount == elementData.length) {
    580                 growByOne();
    581             }
    582             int count = elementCount - location;
    583             if (count > 0) {
    584                 System.arraycopy(elementData, location, elementData,
    585                         location + 1, count);
    586             }
    587             elementData[location] = object;
    588             elementCount++;
    589             modCount++;
    590         } else {
    591             throw new ArrayIndexOutOfBoundsException(location);
    592         }
    593     }
    594 
    595     /**
    596      * Returns if this vector has no elements, a size of zero.
    597      *
    598      * @return {@code true} if this vector has no elements, {@code false}
    599      *         otherwise.
    600      * @see #size
    601      */
    602     @Override
    603     public synchronized boolean isEmpty() {
    604         return elementCount == 0;
    605     }
    606 
    607     /**
    608      * Returns the last element in this vector.
    609      *
    610      * @return the element at the last position.
    611      * @throws NoSuchElementException
    612      *                if this vector is empty.
    613      * @see #elementAt
    614      * @see #firstElement
    615      * @see #size
    616      */
    617     @SuppressWarnings("unchecked")
    618     public synchronized E lastElement() {
    619         try {
    620             return (E) elementData[elementCount - 1];
    621         } catch (IndexOutOfBoundsException e) {
    622             throw new NoSuchElementException();
    623         }
    624     }
    625 
    626     /**
    627      * Searches in this vector for the index of the specified object. The search
    628      * for the object starts at the end and moves towards the start of this
    629      * vector.
    630      *
    631      * @param object
    632      *            the object to find in this vector.
    633      * @return the index in this vector of the specified element, -1 if the
    634      *         element isn't found.
    635      * @see #contains
    636      * @see #indexOf(Object)
    637      * @see #indexOf(Object, int)
    638      */
    639     @Override
    640     public synchronized int lastIndexOf(Object object) {
    641         return lastIndexOf(object, elementCount - 1);
    642     }
    643 
    644     /**
    645      * Searches in this vector for the index of the specified object. The search
    646      * for the object starts at the specified location and moves towards the
    647      * start of this vector.
    648      *
    649      * @param object
    650      *            the object to find in this vector.
    651      * @param location
    652      *            the index at which to start searching.
    653      * @return the index in this vector of the specified element, -1 if the
    654      *         element isn't found.
    655      * @throws ArrayIndexOutOfBoundsException
    656      *                if {@code location >= size()}.
    657      * @see #contains
    658      * @see #indexOf(Object)
    659      * @see #indexOf(Object, int)
    660      */
    661     public synchronized int lastIndexOf(Object object, int location) {
    662         if (location < elementCount) {
    663             if (object != null) {
    664                 for (int i = location; i >= 0; i--) {
    665                     if (object.equals(elementData[i])) {
    666                         return i;
    667                     }
    668                 }
    669             } else {
    670                 for (int i = location; i >= 0; i--) {
    671                     if (elementData[i] == null) {
    672                         return i;
    673                     }
    674                 }
    675             }
    676             return -1;
    677         }
    678         throw new ArrayIndexOutOfBoundsException(location);
    679     }
    680 
    681     /**
    682      * Removes the object at the specified location from this vector. All
    683      * elements with an index bigger than {@code location} have their index
    684      * decreased by 1.
    685      *
    686      * @param location
    687      *            the index of the object to remove.
    688      * @return the removed object.
    689      * @throws IndexOutOfBoundsException
    690      *                if {@code location < 0 || location >= size()}.
    691      */
    692     @SuppressWarnings("unchecked")
    693     @Override
    694     public synchronized E remove(int location) {
    695         if (location < elementCount) {
    696             E result = (E) elementData[location];
    697             elementCount--;
    698             int size = elementCount - location;
    699             if (size > 0) {
    700                 System.arraycopy(elementData, location + 1, elementData,
    701                         location, size);
    702             }
    703             elementData[elementCount] = null;
    704             modCount++;
    705             return result;
    706         }
    707         throw new ArrayIndexOutOfBoundsException(location);
    708     }
    709 
    710     /**
    711      * Removes the first occurrence, starting at the beginning and moving
    712      * towards the end, of the specified object from this vector. All elements
    713      * with an index bigger than the element that gets removed have their index
    714      * decreased by 1.
    715      *
    716      * @param object
    717      *            the object to remove from this vector.
    718      * @return {@code true} if the specified object was found, {@code false}
    719      *         otherwise.
    720      * @see #removeAllElements
    721      * @see #removeElementAt
    722      * @see #size
    723      */
    724     @Override
    725     public boolean remove(Object object) {
    726         return removeElement(object);
    727     }
    728 
    729     /**
    730      * Removes all occurrences in this vector of each object in the specified
    731      * Collection.
    732      *
    733      * @param collection
    734      *            the collection of objects to remove.
    735      * @return {@code true} if this vector is modified, {@code false} otherwise.
    736      * @see #remove(Object)
    737      * @see #contains(Object)
    738      */
    739     @Override
    740     public synchronized boolean removeAll(Collection<?> collection) {
    741         return super.removeAll(collection);
    742     }
    743 
    744     /**
    745      * Removes all elements from this vector, leaving the size zero and the
    746      * capacity unchanged.
    747      *
    748      * @see #isEmpty
    749      * @see #size
    750      */
    751     public synchronized void removeAllElements() {
    752         for (int i = 0; i < elementCount; i++) {
    753             elementData[i] = null;
    754         }
    755         modCount++;
    756         elementCount = 0;
    757     }
    758 
    759     /**
    760      * Removes the first occurrence, starting at the beginning and moving
    761      * towards the end, of the specified object from this vector. All elements
    762      * with an index bigger than the element that gets removed have their index
    763      * decreased by 1.
    764      *
    765      * @param object
    766      *            the object to remove from this vector.
    767      * @return {@code true} if the specified object was found, {@code false}
    768      *         otherwise.
    769      * @see #removeAllElements
    770      * @see #removeElementAt
    771      * @see #size
    772      */
    773     public synchronized boolean removeElement(Object object) {
    774         int index;
    775         if ((index = indexOf(object, 0)) == -1) {
    776             return false;
    777         }
    778         removeElementAt(index);
    779         return true;
    780     }
    781 
    782     /**
    783      * Removes the element found at index position {@code location} from
    784      * this {@code Vector}. All elements with an index bigger than
    785      * {@code location} have their index decreased by 1.
    786      *
    787      * @param location
    788      *            the index of the element to remove.
    789      * @throws ArrayIndexOutOfBoundsException
    790      *                if {@code location < 0 || location >= size()}.
    791      * @see #removeElement
    792      * @see #removeAllElements
    793      * @see #size
    794      */
    795     public synchronized void removeElementAt(int location) {
    796         if (0 <= location && location < elementCount) {
    797             elementCount--;
    798             int size = elementCount - location;
    799             if (size > 0) {
    800                 System.arraycopy(elementData, location + 1, elementData,
    801                         location, size);
    802             }
    803             elementData[elementCount] = null;
    804             modCount++;
    805         } else {
    806             throw new ArrayIndexOutOfBoundsException(location);
    807         }
    808     }
    809 
    810     /**
    811      * Removes the objects in the specified range from the start to the, but not
    812      * including, end index. All elements with an index bigger than or equal to
    813      * {@code end} have their index decreased by {@code end - start}.
    814      *
    815      * @param start
    816      *            the index at which to start removing.
    817      * @param end
    818      *            the index one past the end of the range to remove.
    819      * @throws IndexOutOfBoundsException
    820      *                if {@code start < 0, start > end} or
    821      *                {@code end > size()}.
    822      */
    823     @Override
    824     protected void removeRange(int start, int end) {
    825         if (start >= 0 && start <= end && end <= elementCount) {
    826             if (start == end) {
    827                 return;
    828             }
    829             if (end != elementCount) {
    830                 System.arraycopy(elementData, end, elementData, start,
    831                         elementCount - end);
    832                 int newCount = elementCount - (end - start);
    833                 Arrays.fill(elementData, newCount, elementCount, null);
    834                 elementCount = newCount;
    835             } else {
    836                 Arrays.fill(elementData, start, elementCount, null);
    837                 elementCount = start;
    838             }
    839             modCount++;
    840         } else {
    841             throw new IndexOutOfBoundsException();
    842         }
    843     }
    844 
    845     /**
    846      * Removes all objects from this vector that are not contained in the
    847      * specified collection.
    848      *
    849      * @param collection
    850      *            the collection of objects to retain.
    851      * @return {@code true} if this vector is modified, {@code false} otherwise.
    852      * @see #remove(Object)
    853      */
    854     @Override
    855     public synchronized boolean retainAll(Collection<?> collection) {
    856         return super.retainAll(collection);
    857     }
    858 
    859     /**
    860      * Replaces the element at the specified location in this vector with the
    861      * specified object.
    862      *
    863      * @param location
    864      *            the index at which to put the specified object.
    865      * @param object
    866      *            the object to add to this vector.
    867      * @return the previous element at the location.
    868      * @throws ArrayIndexOutOfBoundsException
    869      *                if {@code location < 0 || location >= size()}.
    870      * @see #size
    871      */
    872     @SuppressWarnings("unchecked")
    873     @Override
    874     public synchronized E set(int location, E object) {
    875         if (location < elementCount) {
    876             E result = (E) elementData[location];
    877             elementData[location] = object;
    878             return result;
    879         }
    880         throw new ArrayIndexOutOfBoundsException(location);
    881     }
    882 
    883     /**
    884      * Replaces the element at the specified location in this vector with the
    885      * specified object.
    886      *
    887      * @param object
    888      *            the object to add to this vector.
    889      * @param location
    890      *            the index at which to put the specified object.
    891      * @throws ArrayIndexOutOfBoundsException
    892      *                if {@code location < 0 || location >= size()}.
    893      * @see #size
    894      */
    895     public synchronized void setElementAt(E object, int location) {
    896         if (location < elementCount) {
    897             elementData[location] = object;
    898         } else {
    899             throw new ArrayIndexOutOfBoundsException(location);
    900         }
    901     }
    902 
    903     /**
    904      * Sets the size of this vector to the specified size. If there are more
    905      * than length elements in this vector, the elements at end are lost. If
    906      * there are less than length elements in the vector, the additional
    907      * elements contain null.
    908      *
    909      * @param length
    910      *            the new size of this vector.
    911      * @see #size
    912      */
    913     public synchronized void setSize(int length) {
    914         if (length == elementCount) {
    915             return;
    916         }
    917         ensureCapacity(length);
    918         if (elementCount > length) {
    919             Arrays.fill(elementData, length, elementCount, null);
    920         }
    921         elementCount = length;
    922         modCount++;
    923     }
    924 
    925     /**
    926      * Returns the number of elements in this vector.
    927      *
    928      * @return the number of elements in this vector.
    929      * @see #elementCount
    930      * @see #lastElement
    931      */
    932     @Override
    933     public synchronized int size() {
    934         return elementCount;
    935     }
    936 
    937     /**
    938      * Returns a List of the specified portion of this vector from the start
    939      * index to one less than the end index. The returned List is backed by this
    940      * vector so changes to one are reflected by the other.
    941      *
    942      * @param start
    943      *            the index at which to start the sublist.
    944      * @param end
    945      *            the index one past the end of the sublist.
    946      * @return a List of a portion of this vector.
    947      * @throws IndexOutOfBoundsException
    948      *                if {@code start < 0} or {@code end > size()}.
    949      * @throws IllegalArgumentException
    950      *                if {@code start > end}.
    951      */
    952     @Override
    953     public synchronized List<E> subList(int start, int end) {
    954         return new Collections.SynchronizedRandomAccessList<E>(super.subList(
    955                 start, end), this);
    956     }
    957 
    958     /**
    959      * Returns a new array containing all elements contained in this vector.
    960      *
    961      * @return an array of the elements from this vector.
    962      */
    963     @Override
    964     public synchronized Object[] toArray() {
    965         Object[] result = new Object[elementCount];
    966         System.arraycopy(elementData, 0, result, 0, elementCount);
    967         return result;
    968     }
    969 
    970     /**
    971      * Returns an array containing all elements contained in this vector. If the
    972      * specified array is large enough to hold the elements, the specified array
    973      * is used, otherwise an array of the same type is created. If the specified
    974      * array is used and is larger than this vector, the array element following
    975      * the collection elements is set to null.
    976      *
    977      * @param contents
    978      *            the array to fill.
    979      * @return an array of the elements from this vector.
    980      * @throws ArrayStoreException
    981      *                if the type of an element in this vector cannot be
    982      *                stored in the type of the specified array.
    983      */
    984     @Override
    985     @SuppressWarnings("unchecked")
    986     public synchronized <T> T[] toArray(T[] contents) {
    987         if (elementCount > contents.length) {
    988             Class<?> ct = contents.getClass().getComponentType();
    989             contents = (T[]) Array.newInstance(ct, elementCount);
    990         }
    991         System.arraycopy(elementData, 0, contents, 0, elementCount);
    992         if (elementCount < contents.length) {
    993             contents[elementCount] = null;
    994         }
    995         return contents;
    996     }
    997 
    998     /**
    999      * Returns the string representation of this vector.
   1000      *
   1001      * @return the string representation of this vector.
   1002      * @see #elements
   1003      */
   1004     @Override
   1005     public synchronized String toString() {
   1006         if (elementCount == 0) {
   1007             return "[]";
   1008         }
   1009         int length = elementCount - 1;
   1010         StringBuilder buffer = new StringBuilder(elementCount * 16);
   1011         buffer.append('[');
   1012         for (int i = 0; i < length; i++) {
   1013             if (elementData[i] == this) {
   1014                 buffer.append("(this Collection)");
   1015             } else {
   1016                 buffer.append(elementData[i]);
   1017             }
   1018             buffer.append(", ");
   1019         }
   1020         if (elementData[length] == this) {
   1021             buffer.append("(this Collection)");
   1022         } else {
   1023             buffer.append(elementData[length]);
   1024         }
   1025         buffer.append(']');
   1026         return buffer.toString();
   1027     }
   1028 
   1029     /**
   1030      * Sets the capacity of this vector to be the same as the size.
   1031      *
   1032      * @see #capacity
   1033      * @see #ensureCapacity
   1034      * @see #size
   1035      */
   1036     public synchronized void trimToSize() {
   1037         if (elementData.length != elementCount) {
   1038             grow(elementCount);
   1039         }
   1040     }
   1041 
   1042     private synchronized void writeObject(ObjectOutputStream stream)
   1043             throws IOException {
   1044         stream.defaultWriteObject();
   1045     }
   1046 }
   1047