001/* Vector.java -- Class that provides growable arrays.
002   Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005, 2006,  
003   Free Software Foundation, Inc.
004
005This file is part of GNU Classpath.
006
007GNU Classpath is free software; you can redistribute it and/or modify
008it under the terms of the GNU General Public License as published by
009the Free Software Foundation; either version 2, or (at your option)
010any later version.
011
012GNU Classpath is distributed in the hope that it will be useful, but
013WITHOUT ANY WARRANTY; without even the implied warranty of
014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015General Public License for more details.
016
017You should have received a copy of the GNU General Public License
018along with GNU Classpath; see the file COPYING.  If not, write to the
019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02002110-1301 USA.
021
022Linking this library statically or dynamically with other modules is
023making a combined work based on this library.  Thus, the terms and
024conditions of the GNU General Public License cover the whole
025combination.
026
027As a special exception, the copyright holders of this library give you
028permission to link this library with independent modules to produce an
029executable, regardless of the license terms of these independent
030modules, and to copy and distribute the resulting executable under
031terms of your choice, provided that you also meet, for each linked
032independent module, the terms and conditions of the license of that
033module.  An independent module is a module which is not derived from
034or based on this library.  If you modify this library, you may extend
035this exception to your version of the library, but you are not
036obligated to do so.  If you do not wish to do so, delete this
037exception statement from your version. */
038
039
040package java.util;
041
042import java.io.IOException;
043import java.io.ObjectOutputStream;
044import java.io.Serializable;
045import 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 */
085public 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}