001    /* Vector.java -- Class that provides growable arrays.
002       Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005, 2006,
003       Free Software Foundation, Inc.
004    
005    This file is part of GNU Classpath.
006    
007    GNU Classpath is free software; you can redistribute it and/or modify
008    it under the terms of the GNU General Public License as published by
009    the Free Software Foundation; either version 2, or (at your option)
010    any later version.
011    
012    GNU Classpath is distributed in the hope that it will be useful, but
013    WITHOUT ANY WARRANTY; without even the implied warranty of
014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015    General Public License for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with GNU Classpath; see the file COPYING.  If not, write to the
019    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020    02110-1301 USA.
021    
022    Linking this library statically or dynamically with other modules is
023    making a combined work based on this library.  Thus, the terms and
024    conditions of the GNU General Public License cover the whole
025    combination.
026    
027    As a special exception, the copyright holders of this library give you
028    permission to link this library with independent modules to produce an
029    executable, regardless of the license terms of these independent
030    modules, and to copy and distribute the resulting executable under
031    terms of your choice, provided that you also meet, for each linked
032    independent module, the terms and conditions of the license of that
033    module.  An independent module is a module which is not derived from
034    or based on this library.  If you modify this library, you may extend
035    this exception to your version of the library, but you are not
036    obligated to do so.  If you do not wish to do so, delete this
037    exception statement from your version. */
038    
039    
040    package java.util;
041    
042    import java.io.IOException;
043    import java.io.ObjectOutputStream;
044    import java.io.Serializable;
045    import java.lang.reflect.Array;
046    
047    /**
048     * The <code>Vector</code> classes implements growable arrays of Objects.
049     * You can access elements in a Vector with an index, just as you
050     * can in a built in array, but Vectors can grow and shrink to accommodate
051     * more or fewer objects.<p>
052     *
053     * Vectors try to mantain efficiency in growing by having a
054     * <code>capacityIncrement</code> that can be specified at instantiation.
055     * When a Vector can no longer hold a new Object, it grows by the amount
056     * in <code>capacityIncrement</code>. If this value is 0, the vector doubles in
057     * size.<p>
058     *
059     * Vector implements the JDK 1.2 List interface, and is therefore a fully
060     * compliant Collection object. The iterators are fail-fast - if external
061     * code structurally modifies the vector, any operation on the iterator will
062     * then throw a {@link ConcurrentModificationException}. The Vector class is
063     * fully synchronized, but the iterators are not. So, when iterating over a
064     * vector, be sure to synchronize on the vector itself.  If you don't want the
065     * expense of synchronization, use ArrayList instead. On the other hand, the
066     * Enumeration of elements() is not thread-safe, nor is it fail-fast; so it
067     * can lead to undefined behavior even in a single thread if you modify the
068     * vector during iteration.<p>
069     *
070     * Note: Some methods, especially those specified by List, specify throwing
071     * {@link IndexOutOfBoundsException}, but it is easier to implement by
072     * throwing the subclass {@link ArrayIndexOutOfBoundsException}. Others
073     * directly specify this subclass.
074     *
075     * @author Scott G. Miller
076     * @author Bryce McKinlay
077     * @author Eric Blake (ebb9@email.byu.edu)
078     * @see Collection
079     * @see List
080     * @see ArrayList
081     * @see LinkedList
082     * @since 1.0
083     * @status updated to 1.4
084     */
085    public class Vector<T> extends AbstractList<T>
086      implements List<T>, RandomAccess, Cloneable, Serializable
087    {
088      /**
089       * Compatible with JDK 1.0+.
090       */
091      private static final long serialVersionUID = -2767605614048989439L;
092    
093      /**
094       * The internal array used to hold members of a Vector. The elements are
095       * in positions 0 through elementCount - 1, and all remaining slots are null.
096       * @serial the elements
097       */
098      protected Object[] elementData;
099    
100      /**
101       * The number of elements currently in the vector, also returned by
102       * {@link #size}.
103       * @serial the size
104       */
105      protected int elementCount;
106    
107      /**
108       * The amount the Vector's internal array should be increased in size when
109       * a new element is added that exceeds the current size of the array,
110       * or when {@link #ensureCapacity} is called. If &lt;= 0, the vector just
111       * doubles in size.
112       * @serial the amount to grow the vector by
113       */
114      protected int capacityIncrement;
115    
116      /**
117       * Constructs an empty vector with an initial size of 10, and
118       * a capacity increment of 0
119       */
120      public Vector()
121      {
122        this(10, 0);
123      }
124    
125      /**
126       * Constructs a vector containing the contents of Collection, in the
127       * order given by the collection.
128       *
129       * @param c collection of elements to add to the new vector
130       * @throws NullPointerException if c is null
131       * @since 1.2
132       */
133      public Vector(Collection<? extends T> c)
134      {
135        elementCount = c.size();
136        elementData = c.toArray(new Object[elementCount]);
137      }
138    
139      /**
140       * Constructs a Vector with the initial capacity and capacity
141       * increment specified.
142       *
143       * @param initialCapacity the initial size of the Vector's internal array
144       * @param capacityIncrement the amount the internal array should be
145       *        increased by when necessary, 0 to double the size
146       * @throws IllegalArgumentException if initialCapacity &lt; 0
147       */
148      public Vector(int initialCapacity, int capacityIncrement)
149      {
150        if (initialCapacity < 0)
151          throw new IllegalArgumentException();
152        elementData = new Object[initialCapacity];
153        this.capacityIncrement = capacityIncrement;
154      }
155    
156      /**
157       * Constructs a Vector with the initial capacity specified, and a capacity
158       * increment of 0 (double in size).
159       *
160       * @param initialCapacity the initial size of the Vector's internal array
161       * @throws IllegalArgumentException if initialCapacity &lt; 0
162       */
163      public Vector(int initialCapacity)
164      {
165        this(initialCapacity, 0);
166      }
167    
168      /**
169       * Copies the contents of the Vector into the provided array.  If the
170       * array is too small to fit all the elements in the Vector, an
171       * {@link IndexOutOfBoundsException} is thrown without modifying the array.
172       * Old elements in the array are overwritten by the new elements.
173       *
174       * @param a target array for the copy
175       * @throws IndexOutOfBoundsException the array is not large enough
176       * @throws NullPointerException the array is null
177       * @see #toArray(Object[])
178       */
179      public synchronized void copyInto(Object[] a)
180      {
181        System.arraycopy(elementData, 0, a, 0, elementCount);
182      }
183    
184      /**
185       * Trims the Vector down to size.  If the internal data array is larger
186       * than the number of Objects its holding, a new array is constructed
187       * that precisely holds the elements. Otherwise this does nothing.
188       */
189      public synchronized void trimToSize()
190      {
191        // Don't bother checking for the case where size() == the capacity of the
192        // vector since that is a much less likely case; it's more efficient to
193        // not do the check and lose a bit of performance in that infrequent case
194    
195        T[] newArray = (T[]) new Object[elementCount];
196        System.arraycopy(elementData, 0, newArray, 0, elementCount);
197        elementData = newArray;
198      }
199    
200      /**
201       * Ensures that <code>minCapacity</code> elements can fit within this Vector.
202       * If <code>elementData</code> is too small, it is expanded as follows:
203       * If the <code>elementCount + capacityIncrement</code> is adequate, that
204       * is the new size. If <code>capacityIncrement</code> is non-zero, the
205       * candidate size is double the current. If that is not enough, the new
206       * size is <code>minCapacity</code>.
207       *
208       * @param minCapacity the desired minimum capacity, negative values ignored
209       */
210      public synchronized void ensureCapacity(int minCapacity)
211      {
212        if (elementData.length >= minCapacity)
213          return;
214    
215        int newCapacity;
216        if (capacityIncrement <= 0)
217          newCapacity = elementData.length * 2;
218        else
219          newCapacity = elementData.length + capacityIncrement;
220    
221        T[] newArray = (T[]) new Object[Math.max(newCapacity, minCapacity)];
222    
223        System.arraycopy(elementData, 0, newArray, 0, elementCount);
224        elementData = newArray;
225      }
226    
227      /**
228       * Explicitly sets the size of the vector (but not necessarily the size of
229       * the internal data array). If the new size is smaller than the old one,
230       * old values that don't fit are lost. If the new size is larger than the
231       * old one, the vector is padded with null entries.
232       *
233       * @param newSize The new size of the internal array
234       * @throws ArrayIndexOutOfBoundsException if the new size is negative
235       */
236      public synchronized void setSize(int newSize)
237      {
238        // Don't bother checking for the case where size() == the capacity of the
239        // vector since that is a much less likely case; it's more efficient to
240        // not do the check and lose a bit of performance in that infrequent case
241        modCount++;
242        ensureCapacity(newSize);
243        if (newSize < elementCount)
244          Arrays.fill(elementData, newSize, elementCount, null);
245        elementCount = newSize;
246      }
247    
248      /**
249       * Returns the size of the internal data array (not the amount of elements
250       * contained in the Vector).
251       *
252       * @return capacity of the internal data array
253       */
254      public synchronized int capacity()
255      {
256        return elementData.length;
257      }
258    
259      /**
260       * Returns the number of elements stored in this Vector.
261       *
262       * @return the number of elements in this Vector
263       */
264      public synchronized int size()
265      {
266        return elementCount;
267      }
268    
269      /**
270       * Returns true if this Vector is empty, false otherwise
271       *
272       * @return true if the Vector is empty, false otherwise
273       */
274      public synchronized boolean isEmpty()
275      {
276        return elementCount == 0;
277      }
278    
279      /**
280       * Returns an Enumeration of the elements of this Vector. The enumeration
281       * visits the elements in increasing index order, but is NOT thread-safe.
282       *
283       * @return an Enumeration
284       * @see #iterator()
285       */
286      // No need to synchronize as the Enumeration is not thread-safe!
287      public Enumeration<T> elements()
288      {
289        return new Enumeration<T>()
290        {
291          private int i = 0;
292    
293          public boolean hasMoreElements()
294          {
295            return i < elementCount;
296          }
297    
298          @SuppressWarnings("unchecked")
299          public T nextElement()
300          {
301            if (i >= elementCount)
302              throw new NoSuchElementException();
303            return (T) elementData[i++];
304          }
305        };
306      }
307    
308      /**
309       * Returns true when <code>elem</code> is contained in this Vector.
310       *
311       * @param elem the element to check
312       * @return true if the object is contained in this Vector, false otherwise
313       */
314      public boolean contains(Object elem)
315      {
316        return indexOf(elem, 0) >= 0;
317      }
318    
319      /**
320       * Returns the first occurrence of <code>elem</code> in the Vector, or -1 if
321       * <code>elem</code> is not found.
322       *
323       * @param elem the object to search for
324       * @return the index of the first occurrence, or -1 if not found
325       */
326      public int indexOf(Object elem)
327      {
328        return indexOf(elem, 0);
329      }
330    
331      /**
332       * Searches the vector starting at <code>index</code> for object
333       * <code>elem</code> and returns the index of the first occurrence of this
334       * Object.  If the object is not found, or index is larger than the size
335       * of the vector, -1 is returned.
336       *
337       * @param e the Object to search for
338       * @param index start searching at this index
339       * @return the index of the next occurrence, or -1 if it is not found
340       * @throws IndexOutOfBoundsException if index &lt; 0
341       */
342      public synchronized int indexOf(Object e, int index)
343      {
344        for (int i = index; i < elementCount; i++)
345          if (equals(e, elementData[i]))
346            return i;
347        return -1;
348      }
349    
350      /**
351       * Returns the last index of <code>elem</code> within this Vector, or -1
352       * if the object is not within the Vector.
353       *
354       * @param elem the object to search for
355       * @return the last index of the object, or -1 if not found
356       */
357      public int lastIndexOf(Object elem)
358      {
359        return lastIndexOf(elem, elementCount - 1);
360      }
361    
362      /**
363       * Returns the index of the first occurrence of <code>elem</code>, when
364       * searching backwards from <code>index</code>.  If the object does not
365       * occur in this Vector, or index is less than 0, -1 is returned.
366       *
367       * @param e the object to search for
368       * @param index the index to start searching in reverse from
369       * @return the index of the Object if found, -1 otherwise
370       * @throws IndexOutOfBoundsException if index &gt;= size()
371       */
372      public synchronized int lastIndexOf(Object e, int index)
373      {
374        checkBoundExclusive(index);
375        for (int i = index; i >= 0; i--)
376          if (equals(e, elementData[i]))
377            return i;
378        return -1;
379      }
380    
381      /**
382       * Returns the Object stored at <code>index</code>.
383       *
384       * @param index the index of the Object to retrieve
385       * @return the object at <code>index</code>
386       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
387       * @see #get(int)
388       */
389      @SuppressWarnings("unchecked")
390      public synchronized T elementAt(int index)
391      {
392        checkBoundExclusive(index);
393        return (T) elementData[index];
394      }
395    
396      /**
397       * Returns the first element (index 0) in the Vector.
398       *
399       * @return the first Object in the Vector
400       * @throws NoSuchElementException the Vector is empty
401       */
402      @SuppressWarnings("unchecked")
403      public synchronized T firstElement()
404      {
405        if (elementCount == 0)
406          throw new NoSuchElementException();
407    
408        return (T) elementData[0];
409      }
410    
411      /**
412       * Returns the last element in the Vector.
413       *
414       * @return the last Object in the Vector
415       * @throws NoSuchElementException the Vector is empty
416       */
417      @SuppressWarnings("unchecked")
418      public synchronized T lastElement()
419      {
420        if (elementCount == 0)
421          throw new NoSuchElementException();
422    
423        return (T) elementData[elementCount - 1];
424      }
425    
426      /**
427       * Changes the element at <code>index</code> to be <code>obj</code>
428       *
429       * @param obj the object to store
430       * @param index the position in the Vector to store the object
431       * @throws ArrayIndexOutOfBoundsException the index is out of range
432       * @see #set(int, Object)
433       */
434      public void setElementAt(T obj, int index)
435      {
436        set(index, obj);
437      }
438    
439      /**
440       * Removes the element at <code>index</code>, and shifts all elements at
441       * positions greater than index to their index - 1.
442       *
443       * @param index the index of the element to remove
444       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size();
445       * @see #remove(int)
446       */
447      public void removeElementAt(int index)
448      {
449        remove(index);
450      }
451    
452      /**
453       * Inserts a new element into the Vector at <code>index</code>.  Any elements
454       * at or greater than index are shifted up one position.
455       *
456       * @param obj the object to insert
457       * @param index the index at which the object is inserted
458       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
459       * @see #add(int, Object)
460       */
461      public synchronized void insertElementAt(T obj, int index)
462      {
463        checkBoundInclusive(index);
464        if (elementCount == elementData.length)
465          ensureCapacity(elementCount + 1);
466        modCount++;
467        System.arraycopy(elementData, index, elementData, index + 1,
468                         elementCount - index);
469        elementCount++;
470        elementData[index] = obj;
471      }
472    
473      /**
474       * Adds an element to the Vector at the end of the Vector.  The vector
475       * is increased by ensureCapacity(size() + 1) if needed.
476       *
477       * @param obj the object to add to the Vector
478       */
479      public synchronized void addElement(T obj)
480      {
481        if (elementCount == elementData.length)
482          ensureCapacity(elementCount + 1);
483        modCount++;
484        elementData[elementCount++] = obj;
485      }
486    
487      /**
488       * Removes the first (the lowest index) occurrence of the given object from
489       * the Vector. If such a remove was performed (the object was found), true
490       * is returned. If there was no such object, false is returned.
491       *
492       * @param obj the object to remove from the Vector
493       * @return true if the Object was in the Vector, false otherwise
494       * @see #remove(Object)
495       */
496      public synchronized boolean removeElement(Object obj)
497      {
498        int idx = indexOf(obj, 0);
499        if (idx >= 0)
500          {
501            remove(idx);
502            return true;
503          }
504        return false;
505      }
506    
507      /**
508       * Removes all elements from the Vector.  Note that this does not
509       * resize the internal data array.
510       *
511       * @see #clear()
512       */
513      public synchronized void removeAllElements()
514      {
515        if (elementCount == 0)
516          return;
517    
518        modCount++;
519        Arrays.fill(elementData, 0, elementCount, null);
520        elementCount = 0;
521      }
522    
523      /**
524       * Creates a new Vector with the same contents as this one. The clone is
525       * shallow; elements are not cloned.
526       *
527       * @return the clone of this vector
528       */
529      public synchronized Object clone()
530      {
531        try
532          {
533            Vector clone = (Vector) super.clone();
534            clone.elementData = (Object[]) elementData.clone();
535            return clone;
536          }
537        catch (CloneNotSupportedException ex)
538          {
539            // Impossible to get here.
540            throw new InternalError(ex.toString());
541          }
542      }
543    
544      /**
545       * Returns an Object array with the contents of this Vector, in the order
546       * they are stored within this Vector.  Note that the Object array returned
547       * is not the internal data array, and that it holds only the elements
548       * within the Vector.  This is similar to creating a new Object[] with the
549       * size of this Vector, then calling Vector.copyInto(yourArray).
550       *
551       * @return an Object[] containing the contents of this Vector in order
552       * @since 1.2
553       */
554      public synchronized Object[] toArray()
555      {
556        Object[] newArray = new Object[elementCount];
557        copyInto(newArray);
558        return newArray;
559      }
560    
561      /**
562       * Returns an array containing the contents of this Vector.
563       * If the provided array is large enough, the contents are copied
564       * into that array, and a null is placed in the position size().
565       * In this manner, you can obtain the size of a Vector by the position
566       * of the null element, if you know the vector does not itself contain
567       * null entries.  If the array is not large enough, reflection is used
568       * to create a bigger one of the same runtime type.
569       *
570       * @param a an array to copy the Vector into if large enough
571       * @return an array with the contents of this Vector in order
572       * @throws ArrayStoreException the runtime type of the provided array
573       *         cannot hold the elements of the Vector
574       * @throws NullPointerException if <code>a</code> is null
575       * @since 1.2
576       */
577      public synchronized <S> S[] toArray(S[] a)
578      {
579        if (a.length < elementCount)
580          a = (S[]) Array.newInstance(a.getClass().getComponentType(),
581                                      elementCount);
582        else if (a.length > elementCount)
583          a[elementCount] = null;
584        System.arraycopy(elementData, 0, a, 0, elementCount);
585        return a;
586      }
587    
588      /**
589       * Returns the element at position <code>index</code>.
590       *
591       * @param index the position from which an element will be retrieved
592       * @return the element at that position
593       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
594       * @since 1.2
595       */
596      public T get(int index)
597      {
598        return elementAt(index);
599      }
600    
601      /**
602       * Puts <code>element</code> into the Vector at position <code>index</code>
603       * and returns the Object that previously occupied that position.
604       *
605       * @param index the index within the Vector to place the Object
606       * @param element the Object to store in the Vector
607       * @return the previous object at the specified index
608       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
609       * @since 1.2
610       */
611      @SuppressWarnings("unchecked")
612      public synchronized T set(int index, T element)
613      {
614        checkBoundExclusive(index);
615        T temp = (T) elementData[index];
616        elementData[index] = element;
617        return temp;
618      }
619    
620      /**
621       * Adds an object to the Vector.
622       *
623       * @param o the element to add to the Vector
624       * @return true, as specified by List
625       * @since 1.2
626       */
627      public boolean add(T o)
628      {
629        addElement(o);
630        return true;
631      }
632    
633      /**
634       * Removes the given Object from the Vector.  If it exists, true
635       * is returned, if not, false is returned.
636       *
637       * @param o the object to remove from the Vector
638       * @return true if the Object existed in the Vector, false otherwise
639       * @since 1.2
640       */
641      public boolean remove(Object o)
642      {
643        return removeElement(o);
644      }
645    
646      /**
647       * Adds an object at the specified index.  Elements at or above
648       * index are shifted up one position.
649       *
650       * @param index the index at which to add the element
651       * @param element the element to add to the Vector
652       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
653       * @since 1.2
654       */
655      public void add(int index, T element)
656      {
657        insertElementAt(element, index);
658      }
659    
660      /**
661       * Removes the element at the specified index, and returns it.
662       *
663       * @param index the position from which to remove the element
664       * @return the object removed
665       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
666       * @since 1.2
667       */
668      @SuppressWarnings("unchecked")
669      public synchronized T remove(int index)
670      {
671        checkBoundExclusive(index);
672        T temp = (T) elementData[index];
673        modCount++;
674        elementCount--;
675        if (index < elementCount)
676          System.arraycopy(elementData, index + 1, elementData, index,
677                           elementCount - index);
678        elementData[elementCount] = null;
679        return temp;
680      }
681    
682      /**
683       * Clears all elements in the Vector and sets its size to 0.
684       */
685      public void clear()
686      {
687        removeAllElements();
688      }
689    
690      /**
691       * Returns true if this Vector contains all the elements in c.
692       *
693       * @param c the collection to compare to
694       * @return true if this vector contains all elements of c
695       * @throws NullPointerException if c is null
696       * @since 1.2
697       */
698      public synchronized boolean containsAll(Collection<?> c)
699      {
700        // Here just for the sychronization.
701        return super.containsAll(c);
702      }
703    
704      /**
705       * Appends all elements of the given collection to the end of this Vector.
706       * Behavior is undefined if the collection is modified during this operation
707       * (for example, if this == c).
708       *
709       * @param c the collection to append
710       * @return true if this vector changed, in other words c was not empty
711       * @throws NullPointerException if c is null
712       * @since 1.2
713       */
714      public synchronized boolean addAll(Collection<? extends T> c)
715      {
716        return addAll(elementCount, c);
717      }
718    
719      /**
720       * Remove from this vector all elements contained in the given collection.
721       *
722       * @param c the collection to filter out
723       * @return true if this vector changed
724       * @throws NullPointerException if c is null
725       * @since 1.2
726       */
727      public synchronized boolean removeAll(Collection<?> c)
728      {
729        // The NullPointerException is thrown implicitly when the Vector
730        // is not empty and c is null. The RI allows null arguments when
731        // the vector is empty. See Mauve test:
732        // gnu/testlet/java/util/Vector/removeAll.java
733    
734        int i;
735        int j;
736        for (i = 0; i < elementCount; i++)
737          if (c.contains(elementData[i]))
738            break;
739        if (i == elementCount)
740          return false;
741    
742        modCount++;
743        for (j = i++; i < elementCount; i++)
744          if (! c.contains(elementData[i]))
745            elementData[j++] = elementData[i];
746        elementCount -= i - j;
747        return true;
748      }
749    
750      /**
751       * Retain in this vector only the elements contained in the given collection.
752       *
753       * @param c the collection to filter by
754       * @return true if this vector changed
755       * @throws NullPointerException if c is null
756       * @since 1.2
757       */
758      public synchronized boolean retainAll(Collection<?> c)
759      {
760        // The NullPointerException is thrown implicitly when the Vector
761        // is not empty and c is null. The RI allows null arguments when
762        // the vector is empty. See Mauve test:
763        // gnu/testlet/java/util/Vector/retainAll.java
764    
765        int i;
766        int j;
767        for (i = 0; i < elementCount; i++)
768          if (! c.contains(elementData[i]))
769            break;
770        if (i == elementCount)
771          return false;
772    
773        modCount++;
774        for (j = i++; i < elementCount; i++)
775          if (c.contains(elementData[i]))
776            elementData[j++] = elementData[i];
777        elementCount -= i - j;
778        return true;
779      }
780    
781      /**
782       * Inserts all elements of the given collection at the given index of
783       * this Vector. Behavior is undefined if the collection is modified during
784       * this operation (for example, if this == c).
785       *
786       * @param c the collection to append
787       * @return true if this vector changed, in other words c was not empty
788       * @throws NullPointerException if c is null
789       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
790       * @since 1.2
791       */
792      public synchronized boolean addAll(int index, Collection<? extends T> c)
793      {
794        checkBoundInclusive(index);
795        Iterator<? extends T> itr = c.iterator();
796        int csize = c.size();
797    
798        modCount++;
799        ensureCapacity(elementCount + csize);
800        int end = index + csize;
801        if (elementCount > 0 && index != elementCount)
802          System.arraycopy(elementData, index,
803                           elementData, end, elementCount - index);
804        elementCount += csize;
805        for ( ; index < end; index++)
806          elementData[index] = itr.next();
807        return (csize > 0);
808      }
809    
810      /**
811       * Compares this to the given object.
812       *
813       * @param o the object to compare to
814       * @return true if the two are equal
815       * @since 1.2
816       */
817      public synchronized boolean equals(Object o)
818      {
819        // Here just for the sychronization.
820        return super.equals(o);
821      }
822    
823      /**
824       * Computes the hashcode of this object.
825       *
826       * @return the hashcode
827       * @since 1.2
828       */
829      public synchronized int hashCode()
830      {
831        // Here just for the sychronization.
832        return super.hashCode();
833      }
834    
835      /**
836       * Returns a string representation of this Vector in the form
837       * "[element0, element1, ... elementN]".
838       *
839       * @return the String representation of this Vector
840       */
841      public synchronized String toString()
842      {
843        // Here just for the sychronization.
844        return super.toString();
845      }
846    
847      /**
848       * Obtain a List view of a subsection of this list, from fromIndex
849       * (inclusive) to toIndex (exclusive). If the two indices are equal, the
850       * sublist is empty. The returned list is modifiable, and changes in one
851       * reflect in the other. If this list is structurally modified in
852       * any way other than through the returned list, the result of any subsequent
853       * operations on the returned list is undefined.
854       * <p>
855       *
856       * @param fromIndex the index that the returned list should start from
857       *        (inclusive)
858       * @param toIndex the index that the returned list should go to (exclusive)
859       * @return a List backed by a subsection of this vector
860       * @throws IndexOutOfBoundsException if fromIndex &lt; 0
861       *         || toIndex &gt; size()
862       * @throws IllegalArgumentException if fromIndex &gt; toIndex
863       * @see ConcurrentModificationException
864       * @since 1.2
865       */
866      public synchronized List<T> subList(int fromIndex, int toIndex)
867      {
868        List<T> sub = super.subList(fromIndex, toIndex);
869        // We must specify the correct object to synchronize upon, hence the
870        // use of a non-public API
871        return new Collections.SynchronizedList<T>(this, sub);
872      }
873    
874      /**
875       * Removes a range of elements from this list.
876       * Does nothing when toIndex is equal to fromIndex.
877       *
878       * @param fromIndex the index to start deleting from (inclusive)
879       * @param toIndex the index to delete up to (exclusive)
880       * @throws IndexOutOfBoundsException if fromIndex &gt; toIndex
881       */
882      // This does not need to be synchronized, because it is only called through
883      // clear() of a sublist, and clear() had already synchronized.
884      protected void removeRange(int fromIndex, int toIndex)
885      {
886        int change = toIndex - fromIndex;
887        if (change > 0)
888          {
889            modCount++;
890            System.arraycopy(elementData, toIndex, elementData, fromIndex,
891                             elementCount - toIndex);
892            int save = elementCount;
893            elementCount -= change;
894            Arrays.fill(elementData, elementCount, save, null);
895          }
896        else if (change < 0)
897          throw new IndexOutOfBoundsException();
898      }
899    
900      /**
901       * Checks that the index is in the range of possible elements (inclusive).
902       *
903       * @param index the index to check
904       * @throws ArrayIndexOutOfBoundsException if index &gt; size
905       */
906      private void checkBoundInclusive(int index)
907      {
908        // Implementation note: we do not check for negative ranges here, since
909        // use of a negative index will cause an ArrayIndexOutOfBoundsException
910        // with no effort on our part.
911        if (index > elementCount)
912          raiseBoundsError(index, " > ");
913      }
914    
915      /**
916       * Checks that the index is in the range of existing elements (exclusive).
917       *
918       * @param index the index to check
919       * @throws ArrayIndexOutOfBoundsException if index &gt;= size
920       */
921      private void checkBoundExclusive(int index)
922      {
923        // Implementation note: we do not check for negative ranges here, since
924        // use of a negative index will cause an ArrayIndexOutOfBoundsException
925        // with no effort on our part.
926        if (index >= elementCount)
927          raiseBoundsError(index, " >= ");
928      }
929    
930      /**
931       * Raise the ArrayIndexOfOutBoundsException.
932       *
933       * @param index the index of the access
934       * @param operator the operator to include in the error message
935       * @throws IndexOutOfBoundsException unconditionally
936       */
937      private void raiseBoundsError(int index, String operator)
938      {
939        // Implementaion note: put in a separate method to make the JITs job easier
940        // (separate common from uncommon code at method boundaries when trivial to
941        // do so).
942        throw new ArrayIndexOutOfBoundsException(index + operator + elementCount);
943      }
944    
945      /**
946       * Serializes this object to the given stream.
947       *
948       * @param s the stream to write to
949       * @throws IOException if the underlying stream fails
950       * @serialData just calls default write function
951       */
952      private synchronized void writeObject(ObjectOutputStream s)
953        throws IOException
954      {
955        s.defaultWriteObject();
956      }
957    
958    }