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 T[] 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((T[]) 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 = (T[]) 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          public T nextElement()
299          {
300            if (i >= elementCount)
301              throw new NoSuchElementException();
302            return elementData[i++];
303          }
304        };
305      }
306    
307      /**
308       * Returns true when <code>elem</code> is contained in this Vector.
309       *
310       * @param elem the element to check
311       * @return true if the object is contained in this Vector, false otherwise
312       */
313      public boolean contains(Object elem)
314      {
315        return indexOf(elem, 0) >= 0;
316      }
317    
318      /**
319       * Returns the first occurrence of <code>elem</code> in the Vector, or -1 if
320       * <code>elem</code> is not found.
321       *
322       * @param elem the object to search for
323       * @return the index of the first occurrence, or -1 if not found
324       */
325      public int indexOf(Object elem)
326      {
327        return indexOf(elem, 0);
328      }
329    
330      /**
331       * Searches the vector starting at <code>index</code> for object
332       * <code>elem</code> and returns the index of the first occurrence of this
333       * Object.  If the object is not found, or index is larger than the size
334       * of the vector, -1 is returned.
335       *
336       * @param e the Object to search for
337       * @param index start searching at this index
338       * @return the index of the next occurrence, or -1 if it is not found
339       * @throws IndexOutOfBoundsException if index &lt; 0
340       */
341      public synchronized int indexOf(Object e, int index)
342      {
343        for (int i = index; i < elementCount; i++)
344          if (equals(e, elementData[i]))
345            return i;
346        return -1;
347      }
348    
349      /**
350       * Returns the last index of <code>elem</code> within this Vector, or -1
351       * if the object is not within the Vector.
352       *
353       * @param elem the object to search for
354       * @return the last index of the object, or -1 if not found
355       */
356      public int lastIndexOf(Object elem)
357      {
358        return lastIndexOf(elem, elementCount - 1);
359      }
360    
361      /**
362       * Returns the index of the first occurrence of <code>elem</code>, when
363       * searching backwards from <code>index</code>.  If the object does not
364       * occur in this Vector, or index is less than 0, -1 is returned.
365       *
366       * @param e the object to search for
367       * @param index the index to start searching in reverse from
368       * @return the index of the Object if found, -1 otherwise
369       * @throws IndexOutOfBoundsException if index &gt;= size()
370       */
371      public synchronized int lastIndexOf(Object e, int index)
372      {
373        checkBoundExclusive(index);
374        for (int i = index; i >= 0; i--)
375          if (equals(e, elementData[i]))
376            return i;
377        return -1;
378      }
379    
380      /**
381       * Returns the Object stored at <code>index</code>.
382       *
383       * @param index the index of the Object to retrieve
384       * @return the object at <code>index</code>
385       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
386       * @see #get(int)
387       */
388      public synchronized T elementAt(int index)
389      {
390        checkBoundExclusive(index);
391        return elementData[index];
392      }
393    
394      /**
395       * Returns the first element (index 0) in the Vector.
396       *
397       * @return the first Object in the Vector
398       * @throws NoSuchElementException the Vector is empty
399       */
400      public synchronized T firstElement()
401      {
402        if (elementCount == 0)
403          throw new NoSuchElementException();
404    
405        return elementData[0];
406      }
407    
408      /**
409       * Returns the last element in the Vector.
410       *
411       * @return the last Object in the Vector
412       * @throws NoSuchElementException the Vector is empty
413       */
414      public synchronized T lastElement()
415      {
416        if (elementCount == 0)
417          throw new NoSuchElementException();
418    
419        return elementData[elementCount - 1];
420      }
421    
422      /**
423       * Changes the element at <code>index</code> to be <code>obj</code>
424       *
425       * @param obj the object to store
426       * @param index the position in the Vector to store the object
427       * @throws ArrayIndexOutOfBoundsException the index is out of range
428       * @see #set(int, Object)
429       */
430      public void setElementAt(T obj, int index)
431      {
432        set(index, obj);
433      }
434    
435      /**
436       * Removes the element at <code>index</code>, and shifts all elements at
437       * positions greater than index to their index - 1.
438       *
439       * @param index the index of the element to remove
440       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size();
441       * @see #remove(int)
442       */
443      public void removeElementAt(int index)
444      {
445        remove(index);
446      }
447    
448      /**
449       * Inserts a new element into the Vector at <code>index</code>.  Any elements
450       * at or greater than index are shifted up one position.
451       *
452       * @param obj the object to insert
453       * @param index the index at which the object is inserted
454       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
455       * @see #add(int, Object)
456       */
457      public synchronized void insertElementAt(T obj, int index)
458      {
459        checkBoundInclusive(index);
460        if (elementCount == elementData.length)
461          ensureCapacity(elementCount + 1);
462        modCount++;
463        System.arraycopy(elementData, index, elementData, index + 1,
464                         elementCount - index);
465        elementCount++;
466        elementData[index] = obj;
467      }
468    
469      /**
470       * Adds an element to the Vector at the end of the Vector.  The vector
471       * is increased by ensureCapacity(size() + 1) if needed.
472       *
473       * @param obj the object to add to the Vector
474       */
475      public synchronized void addElement(T obj)
476      {
477        if (elementCount == elementData.length)
478          ensureCapacity(elementCount + 1);
479        modCount++;
480        elementData[elementCount++] = obj;
481      }
482    
483      /**
484       * Removes the first (the lowest index) occurrence of the given object from
485       * the Vector. If such a remove was performed (the object was found), true
486       * is returned. If there was no such object, false is returned.
487       *
488       * @param obj the object to remove from the Vector
489       * @return true if the Object was in the Vector, false otherwise
490       * @see #remove(Object)
491       */
492      public synchronized boolean removeElement(Object obj)
493      {
494        int idx = indexOf(obj, 0);
495        if (idx >= 0)
496          {
497            remove(idx);
498            return true;
499          }
500        return false;
501      }
502    
503      /**
504       * Removes all elements from the Vector.  Note that this does not
505       * resize the internal data array.
506       *
507       * @see #clear()
508       */
509      public synchronized void removeAllElements()
510      {
511        if (elementCount == 0)
512          return;
513    
514        modCount++;
515        Arrays.fill(elementData, 0, elementCount, null);
516        elementCount = 0;
517      }
518    
519      /**
520       * Creates a new Vector with the same contents as this one. The clone is
521       * shallow; elements are not cloned.
522       *
523       * @return the clone of this vector
524       */
525      public synchronized Object clone()
526      {
527        try
528          {
529            Vector clone = (Vector) super.clone();
530            clone.elementData = (Object[]) elementData.clone();
531            return clone;
532          }
533        catch (CloneNotSupportedException ex)
534          {
535            // Impossible to get here.
536            throw new InternalError(ex.toString());
537          }
538      }
539    
540      /**
541       * Returns an Object array with the contents of this Vector, in the order
542       * they are stored within this Vector.  Note that the Object array returned
543       * is not the internal data array, and that it holds only the elements
544       * within the Vector.  This is similar to creating a new Object[] with the
545       * size of this Vector, then calling Vector.copyInto(yourArray).
546       *
547       * @return an Object[] containing the contents of this Vector in order
548       * @since 1.2
549       */
550      public synchronized Object[] toArray()
551      {
552        Object[] newArray = new Object[elementCount];
553        copyInto(newArray);
554        return newArray;
555      }
556    
557      /**
558       * Returns an array containing the contents of this Vector.
559       * If the provided array is large enough, the contents are copied
560       * into that array, and a null is placed in the position size().
561       * In this manner, you can obtain the size of a Vector by the position
562       * of the null element, if you know the vector does not itself contain
563       * null entries.  If the array is not large enough, reflection is used
564       * to create a bigger one of the same runtime type.
565       *
566       * @param a an array to copy the Vector into if large enough
567       * @return an array with the contents of this Vector in order
568       * @throws ArrayStoreException the runtime type of the provided array
569       *         cannot hold the elements of the Vector
570       * @throws NullPointerException if <code>a</code> is null
571       * @since 1.2
572       */
573      public synchronized <S> S[] toArray(S[] a)
574      {
575        if (a.length < elementCount)
576          a = (S[]) Array.newInstance(a.getClass().getComponentType(),
577                                      elementCount);
578        else if (a.length > elementCount)
579          a[elementCount] = null;
580        System.arraycopy(elementData, 0, a, 0, elementCount);
581        return a;
582      }
583    
584      /**
585       * Returns the element at position <code>index</code>.
586       *
587       * @param index the position from which an element will be retrieved
588       * @return the element at that position
589       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
590       * @since 1.2
591       */
592      public T get(int index)
593      {
594        return elementAt(index);
595      }
596    
597      /**
598       * Puts <code>element</code> into the Vector at position <code>index</code>
599       * and returns the Object that previously occupied that position.
600       *
601       * @param index the index within the Vector to place the Object
602       * @param element the Object to store in the Vector
603       * @return the previous object at the specified index
604       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
605       * @since 1.2
606       */
607      public synchronized T set(int index, T element)
608      {
609        checkBoundExclusive(index);
610        T temp = elementData[index];
611        elementData[index] = element;
612        return temp;
613      }
614    
615      /**
616       * Adds an object to the Vector.
617       *
618       * @param o the element to add to the Vector
619       * @return true, as specified by List
620       * @since 1.2
621       */
622      public boolean add(T o)
623      {
624        addElement(o);
625        return true;
626      }
627    
628      /**
629       * Removes the given Object from the Vector.  If it exists, true
630       * is returned, if not, false is returned.
631       *
632       * @param o the object to remove from the Vector
633       * @return true if the Object existed in the Vector, false otherwise
634       * @since 1.2
635       */
636      public boolean remove(Object o)
637      {
638        return removeElement(o);
639      }
640    
641      /**
642       * Adds an object at the specified index.  Elements at or above
643       * index are shifted up one position.
644       *
645       * @param index the index at which to add the element
646       * @param element the element to add to the Vector
647       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
648       * @since 1.2
649       */
650      public void add(int index, T element)
651      {
652        insertElementAt(element, index);
653      }
654    
655      /**
656       * Removes the element at the specified index, and returns it.
657       *
658       * @param index the position from which to remove the element
659       * @return the object removed
660       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
661       * @since 1.2
662       */
663      public synchronized T remove(int index)
664      {
665        checkBoundExclusive(index);
666        T temp = elementData[index];
667        modCount++;
668        elementCount--;
669        if (index < elementCount)
670          System.arraycopy(elementData, index + 1, elementData, index,
671                           elementCount - index);
672        elementData[elementCount] = null;
673        return temp;
674      }
675    
676      /**
677       * Clears all elements in the Vector and sets its size to 0.
678       */
679      public void clear()
680      {
681        removeAllElements();
682      }
683    
684      /**
685       * Returns true if this Vector contains all the elements in c.
686       *
687       * @param c the collection to compare to
688       * @return true if this vector contains all elements of c
689       * @throws NullPointerException if c is null
690       * @since 1.2
691       */
692      public synchronized boolean containsAll(Collection<?> c)
693      {
694        // Here just for the sychronization.
695        return super.containsAll(c);
696      }
697    
698      /**
699       * Appends all elements of the given collection to the end of this Vector.
700       * Behavior is undefined if the collection is modified during this operation
701       * (for example, if this == c).
702       *
703       * @param c the collection to append
704       * @return true if this vector changed, in other words c was not empty
705       * @throws NullPointerException if c is null
706       * @since 1.2
707       */
708      public synchronized boolean addAll(Collection<? extends T> c)
709      {
710        return addAll(elementCount, c);
711      }
712    
713      /**
714       * Remove from this vector all elements contained in the given collection.
715       *
716       * @param c the collection to filter out
717       * @return true if this vector changed
718       * @throws NullPointerException if c is null
719       * @since 1.2
720       */
721      public synchronized boolean removeAll(Collection<?> c)
722      {
723        // The NullPointerException is thrown implicitly when the Vector
724        // is not empty and c is null. The RI allows null arguments when
725        // the vector is empty. See Mauve test:
726        // gnu/testlet/java/util/Vector/removeAll.java
727    
728        int i;
729        int j;
730        for (i = 0; i < elementCount; i++)
731          if (c.contains(elementData[i]))
732            break;
733        if (i == elementCount)
734          return false;
735    
736        modCount++;
737        for (j = i++; i < elementCount; i++)
738          if (! c.contains(elementData[i]))
739            elementData[j++] = elementData[i];
740        elementCount -= i - j;
741        return true;
742      }
743    
744      /**
745       * Retain in this vector only the elements contained in the given collection.
746       *
747       * @param c the collection to filter by
748       * @return true if this vector changed
749       * @throws NullPointerException if c is null
750       * @since 1.2
751       */
752      public synchronized boolean retainAll(Collection<?> c)
753      {
754        // The NullPointerException is thrown implicitly when the Vector
755        // is not empty and c is null. The RI allows null arguments when
756        // the vector is empty. See Mauve test:
757        // gnu/testlet/java/util/Vector/retainAll.java
758    
759        int i;
760        int j;
761        for (i = 0; i < elementCount; i++)
762          if (! c.contains(elementData[i]))
763            break;
764        if (i == elementCount)
765          return false;
766    
767        modCount++;
768        for (j = i++; i < elementCount; i++)
769          if (c.contains(elementData[i]))
770            elementData[j++] = elementData[i];
771        elementCount -= i - j;
772        return true;
773      }
774    
775      /**
776       * Inserts all elements of the given collection at the given index of
777       * this Vector. Behavior is undefined if the collection is modified during
778       * this operation (for example, if this == c).
779       *
780       * @param c the collection to append
781       * @return true if this vector changed, in other words c was not empty
782       * @throws NullPointerException if c is null
783       * @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
784       * @since 1.2
785       */
786      public synchronized boolean addAll(int index, Collection<? extends T> c)
787      {
788        checkBoundInclusive(index);
789        Iterator<? extends T> itr = c.iterator();
790        int csize = c.size();
791    
792        modCount++;
793        ensureCapacity(elementCount + csize);
794        int end = index + csize;
795        if (elementCount > 0 && index != elementCount)
796          System.arraycopy(elementData, index,
797                           elementData, end, elementCount - index);
798        elementCount += csize;
799        for ( ; index < end; index++)
800          elementData[index] = itr.next();
801        return (csize > 0);
802      }
803    
804      /**
805       * Compares this to the given object.
806       *
807       * @param o the object to compare to
808       * @return true if the two are equal
809       * @since 1.2
810       */
811      public synchronized boolean equals(Object o)
812      {
813        // Here just for the sychronization.
814        return super.equals(o);
815      }
816    
817      /**
818       * Computes the hashcode of this object.
819       *
820       * @return the hashcode
821       * @since 1.2
822       */
823      public synchronized int hashCode()
824      {
825        // Here just for the sychronization.
826        return super.hashCode();
827      }
828    
829      /**
830       * Returns a string representation of this Vector in the form
831       * "[element0, element1, ... elementN]".
832       *
833       * @return the String representation of this Vector
834       */
835      public synchronized String toString()
836      {
837        // Here just for the sychronization.
838        return super.toString();
839      }
840    
841      /**
842       * Obtain a List view of a subsection of this list, from fromIndex
843       * (inclusive) to toIndex (exclusive). If the two indices are equal, the
844       * sublist is empty. The returned list is modifiable, and changes in one
845       * reflect in the other. If this list is structurally modified in
846       * any way other than through the returned list, the result of any subsequent
847       * operations on the returned list is undefined.
848       * <p>
849       *
850       * @param fromIndex the index that the returned list should start from
851       *        (inclusive)
852       * @param toIndex the index that the returned list should go to (exclusive)
853       * @return a List backed by a subsection of this vector
854       * @throws IndexOutOfBoundsException if fromIndex &lt; 0
855       *         || toIndex &gt; size()
856       * @throws IllegalArgumentException if fromIndex &gt; toIndex
857       * @see ConcurrentModificationException
858       * @since 1.2
859       */
860      public synchronized List<T> subList(int fromIndex, int toIndex)
861      {
862        List<T> sub = super.subList(fromIndex, toIndex);
863        // We must specify the correct object to synchronize upon, hence the
864        // use of a non-public API
865        return new Collections.SynchronizedList<T>(this, sub);
866      }
867    
868      /**
869       * Removes a range of elements from this list.
870       * Does nothing when toIndex is equal to fromIndex.
871       *
872       * @param fromIndex the index to start deleting from (inclusive)
873       * @param toIndex the index to delete up to (exclusive)
874       * @throws IndexOutOfBoundsException if fromIndex &gt; toIndex
875       */
876      // This does not need to be synchronized, because it is only called through
877      // clear() of a sublist, and clear() had already synchronized.
878      protected void removeRange(int fromIndex, int toIndex)
879      {
880        int change = toIndex - fromIndex;
881        if (change > 0)
882          {
883            modCount++;
884            System.arraycopy(elementData, toIndex, elementData, fromIndex,
885                             elementCount - toIndex);
886            int save = elementCount;
887            elementCount -= change;
888            Arrays.fill(elementData, elementCount, save, null);
889          }
890        else if (change < 0)
891          throw new IndexOutOfBoundsException();
892      }
893    
894      /**
895       * Checks that the index is in the range of possible elements (inclusive).
896       *
897       * @param index the index to check
898       * @throws ArrayIndexOutOfBoundsException if index &gt; size
899       */
900      private void checkBoundInclusive(int index)
901      {
902        // Implementation note: we do not check for negative ranges here, since
903        // use of a negative index will cause an ArrayIndexOutOfBoundsException
904        // with no effort on our part.
905        if (index > elementCount)
906          throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount);
907      }
908    
909      /**
910       * Checks that the index is in the range of existing elements (exclusive).
911       *
912       * @param index the index to check
913       * @throws ArrayIndexOutOfBoundsException if index &gt;= size
914       */
915      private void checkBoundExclusive(int index)
916      {
917        // Implementation note: we do not check for negative ranges here, since
918        // use of a negative index will cause an ArrayIndexOutOfBoundsException
919        // with no effort on our part.
920        if (index >= elementCount)
921          throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
922      }
923    
924      /**
925       * Serializes this object to the given stream.
926       *
927       * @param s the stream to write to
928       * @throws IOException if the underlying stream fails
929       * @serialData just calls default write function
930       */
931      private synchronized void writeObject(ObjectOutputStream s)
932        throws IOException
933      {
934        s.defaultWriteObject();
935      }
936    
937    }