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