Vector introduction
Vector is also based on arrays. It is a dynamic array whose capacity can grow automatically.
Vector is introduced by JDK 1.0, many of its implementation methods have added synchronization statements, so it is thread-safe (in fact, it is only relatively safe, sometimes it is necessary to add synchronization statements to ensure thread security), which can be used in multi-threaded environment.
Vector has no Serializable interface, so it does not support serialization, implements Cloneable interface, can be cloned, implements Random Access interface, and supports fast random access.
Vector Source Analysis
The source code for Vector is as follows (with more detailed comments added):
- package java.util;
- public class Vector<E>
- extends AbstractList<E>
- implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- {
- //Array of data stored in Vector
- protected Object[] elementData;
- //Number of actual data
- protected int elementCount;
- //Capacity growth factor
- protected int capacityIncrement;
- //Sequential version number of Vector
- private static final long serialVersionUID = -2767605614048989439L;
- //Vector constructor. The default capacity is 10.
- public Vector() {
- this(10);
- }
- //Constructor specifying the size of Vector capacity
- public Vector(int initialCapacity) {
- this(initialCapacity, 0);
- }
- //Specify the constructor of Vector's "capacity size" and "growth factor"
- public Vector(int initialCapacity, int capacityIncrement) {
- super();
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal Capacity: "+
- initialCapacity);
- //Create a new array with initial capacity.
- this.elementData = new Object[initialCapacity];
- //Setting capacity growth factor
- this.capacityIncrement = capacityIncrement;
- }
- //Specifies the Vector constructor for the collection.
- public Vector(Collection<? extends E> c) {
- //Get an array of sets (c) and assign it to elementData
- elementData = c.toArray();
- //Set the array length
- elementCount = elementData.length;
- // c.toArray might (incorrectly) not return Object[] (see 6260652)
- if (elementData.getClass() != Object[].class)
- elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
- }
- //Copy all elements of the array Vector into the array anArray.
- public synchronized void copyInto(Object[] anArray) {
- System.arraycopy(elementData, 0, anArray, 0, elementCount);
- }
- //Set the current capacity value to = the number of actual elements
- public synchronized void trimToSize() {
- modCount++;
- int oldCapacity = elementData.length;
- if (elementCount < oldCapacity) {
- elementData = Arrays.copyOf(elementData, elementCount);
- }
- }
- //Confirmation of the help function for Vector Capacity
- private void ensureCapacityHelper(int minCapacity) {
- int oldCapacity = elementData.length;
- //When Vector's capacity is insufficient to accommodate all the current elements, increase the capacity size.
- //If the capacity increment coefficient is greater than 0 (i.e. capacityIncrement > 0), the capacity will increase when capacityIncrement.
- //Otherwise, the capacity will be doubled.
- if (minCapacity > oldCapacity) {
- Object[] oldData = elementData;
- int newCapacity = (capacityIncrement > 0) ?
- (oldCapacity + capacityIncrement) : (oldCapacity * 2);
- if (newCapacity < minCapacity) {
- newCapacity = minCapacity;
- }
- elementData = Arrays.copyOf(elementData, newCapacity);
- }
- }
- //Determine the capacity of Vector.
- public synchronized void ensureCapacity(int minCapacity) {
- //Change statistics of Vector + 1
- modCount++;
- ensureCapacityHelper(minCapacity);
- }
- //Set the capacity value to newSize
- public synchronized void setSize(int newSize) {
- modCount++;
- if (newSize > elementCount) {
- //If "newSize" is larger than Vector capacity, adjust Vector size.
- ensureCapacityHelper(newSize);
- } else {
- //If "newSize" is less than/equal to Vector capacity, the elements starting at the newSize location are set to null.
- for (int i = newSize ; i < elementCount ; i++) {
- elementData[i] = null;
- }
- }
- elementCount = newSize;
- }
- //Return "Vector's total capacity"
- public synchronized int capacity() {
- return elementData.length;
- }
- //Returns the actual size of the Vector, that is, the number of elements in the Vector.
- public synchronized int size() {
- return elementCount;
- }
- //Judging whether Vector is empty
- public synchronized boolean isEmpty() {
- return elementCount == 0;
- }
- //Return Enumeration for all elements in Vector
- public Enumeration<E> elements() {
- //Enumeration through anonymous classes
- return new Enumeration<E>() {
- int count = 0;
- //Is there the next element?
- public boolean hasMoreElements() {
- return count < elementCount;
- }
- //Get the next element.
- public E nextElement() {
- synchronized (Vector.this) {
- if (count < elementCount) {
- return (E)elementData[count++];
- }
- }
- throw new NoSuchElementException("Vector Enumeration");
- }
- };
- }
- //Returns whether the Vector contains an object (o)
- public boolean contains(Object o) {
- return indexOf(o, 0) >= 0;
- }
- //Look back at the element (o) from the index position.
- //If found, the index value of the element is returned; otherwise, return -1.
- public synchronized int indexOf(Object o, int index) {
- if (o == null) {
- //If the search element is null, the null element is found forward and its corresponding ordinal number is returned.
- for (int i = index ; i < elementCount ; i++)
- if (elementData[i]==null)
- return i;
- } else {
- //If the element is not null, the element is found forward and its corresponding serial number is returned.
- for (int i = index ; i < elementCount ; i++)
- if (o.equals(elementData[i]))
- return i;
- }
- return -1;
- }
- //Find and return the index value of element (o) in Vector
- public int indexOf(Object o) {
- return indexOf(o, 0);
- }
- //Look for elements (o) backwards and forwards. And return the index of the element.
- public synchronized int lastIndexOf(Object o) {
- return lastIndexOf(o, elementCount-1);
- }
- //Look for elements (o) backwards and forwards. The starting position is the number of index es from the front to the back;
- //If found, return the "index value" of the element; otherwise, return - 1.
- public synchronized int lastIndexOf(Object o, int index) {
- if (index >= elementCount)
- throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
- if (o == null) {
- //If the finding element is null, the null element is retrieved and its corresponding serial number is returned.
- for (int i = index; i >= 0; i--)
- if (elementData[i]==null)
- return i;
- } else {
- //If the element is not null, the element is retrieved and its corresponding serial number is returned.
- for (int i = index; i >= 0; i--)
- if (o.equals(elementData[i]))
- return i;
- }
- return -1;
- }
- //Returns the element at the index position in Vector.
- //If index ends, an exception is thrown.
- public synchronized E elementAt(int index) {
- if (index >= elementCount) {
- throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
- }
- return (E)elementData[index];
- }
- //Get the first element in Vector.
- //If it fails, throw an exception!
- public synchronized E firstElement() {
- if (elementCount == 0) {
- throw new NoSuchElementException();
- }
- return (E)elementData[0];
- }
- //Get the last element in Vector.
- //If it fails, throw an exception!
- public synchronized E lastElement() {
- if (elementCount == 0) {
- throw new NoSuchElementException();
- }
- return (E)elementData[elementCount - 1];
- }
- //Set the element value of index position to obj
- public synchronized void setElementAt(E obj, int index) {
- if (index >= elementCount) {
- throw new ArrayIndexOutOfBoundsException(index + " >= " +
- elementCount);
- }
- elementData[index] = obj;
- }
- //Delete the element in the index position
- public synchronized void removeElementAt(int index) {
- modCount++;
- if (index >= elementCount) {
- throw new ArrayIndexOutOfBoundsException(index + " >= " +
- elementCount);
- } else if (index < 0) {
- throw new ArrayIndexOutOfBoundsException(index);
- }
- int j = elementCount - index - 1;
- if (j > 0) {
- System.arraycopy(elementData, index + 1, elementData, index, j);
- }
- elementCount--;
- elementData[elementCount] = null; /* to let gc do its work */
- }
- //Insert the element (obj) at the index position
- public synchronized void insertElementAt(E obj, int index) {
- modCount++;
- if (index > elementCount) {
- throw new ArrayIndexOutOfBoundsException(index
- + " > " + elementCount);
- }
- ensureCapacityHelper(elementCount + 1);
- System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
- elementData[index] = obj;
- elementCount++;
- }
- //Add "element obj" to the end of Vector
- public synchronized void addElement(E obj) {
- modCount++;
- ensureCapacityHelper(elementCount + 1);
- elementData[elementCount++] = obj;
- }
- //Find and delete the element obj in Vector.
- //If successful, return true; otherwise, return false.
- public synchronized boolean removeElement(Object obj) {
- modCount++;
- int i = indexOf(obj);
- if (i >= 0) {
- removeElementAt(i);
- return true;
- }
- return false;
- }
- //Delete all elements in Vector
- public synchronized void removeAllElements() {
- modCount++;
- //Set all elements in Vector to null
- for (int i = 0; i < elementCount; i++)
- elementData[i] = null;
- elementCount = 0;
- }
- //Clone function
- public synchronized Object clone() {
- try {
- Vector<E> v = (Vector<E>) super.clone();
- //Copy all elements of the current Vector into v.
- v.elementData = Arrays.copyOf(elementData, elementCount);
- v.modCount = 0;
- return v;
- } catch (CloneNotSupportedException e) {
- // this shouldn't happen, since we are Cloneable
- throw new InternalError();
- }
- }
- //Returns the Object array.
- public synchronized Object[] toArray() {
- return Arrays.copyOf(elementData, elementCount);
- }
- //Returns an array of templates for Vector. The so-called template array means that T can be set to any data type.
- public synchronized <T> T[] toArray(T[] a) {
- //If the size of array a is less than the number of elements of Vector;
- //Create a new T [] array with the size of "Number of Vector Elements" and copy all "Vector" into the new array.
- if (a.length < elementCount)
- return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());
- //If the size of array a >= the number of elements of Vector;
- //Copy all elements of Vector into array a.
- System.arraycopy(elementData, 0, a, 0, elementCount);
- if (a.length > elementCount)
- a[elementCount] = null;
- return a;
- }
- //Get the element at the index location
- public synchronized E get(int index) {
- if (index >= elementCount)
- throw new ArrayIndexOutOfBoundsException(index);
- return (E)elementData[index];
- }
- //Set the value of index to element. And returns the original value of the index position.
- public synchronized E set(int index, E element) {
- if (index >= elementCount)
- throw new ArrayIndexOutOfBoundsException(index);
- Object oldValue = elementData[index];
- elementData[index] = element;
- return (E)oldValue;
- }
- //Add "element e" to the end of Vector.
- public synchronized boolean add(E e) {
- modCount++;
- ensureCapacityHelper(elementCount + 1);
- elementData[elementCount++] = e;
- return true;
- }
- //Delete element o in Vector
- public boolean remove(Object o) {
- return removeElement(o);
- }
- //Add element at index position
- public void add(int index, E element) {
- insertElementAt(element, index);
- }
- //Delete the element in the index position and return the original value of the index position.
- public synchronized E remove(int index) {
- modCount++;
- if (index >= elementCount)
- throw new ArrayIndexOutOfBoundsException(index);
- Object oldValue = elementData[index];
- int numMoved = elementCount - index - 1;
- if (numMoved > 0)
- System.arraycopy(elementData, index+1, elementData, index,
- numMoved);
- elementData[--elementCount] = null; // Let gc do its work
- return (E)oldValue;
- }
- //Empty Vector
- public void clear() {
- removeAllElements();
- }
- //Returns whether Vector contains collection c
- public synchronized boolean containsAll(Collection<?> c) {
- return super.containsAll(c);
- }
- //Add collection c to Vector
- public synchronized boolean addAll(Collection<? extends E> c) {
- modCount++;
- Object[] a = c.toArray();
- int numNew = a.length;
- ensureCapacityHelper(elementCount + numNew);
- //Copy all elements of set c into the array elementData.
- System.arraycopy(a, 0, elementData, elementCount, numNew);
- elementCount += numNew;
- return numNew != 0;
- }
- //Delete all elements of set c
- public synchronized boolean removeAll(Collection<?> c) {
- return super.removeAll(c);
- }
- //Delete "Elements in non-set c"
- public synchronized boolean retainAll(Collection<?> c) {
- return super.retainAll(c);
- }
- //From the index location, add collection c to Vector.
- public synchronized boolean addAll(int index, Collection<? extends E> c) {
- modCount++;
- if (index < 0 || index > elementCount)
- throw new ArrayIndexOutOfBoundsException(index);
- Object[] a = c.toArray();
- int numNew = a.length;
- ensureCapacityHelper(elementCount + numNew);
- int numMoved = elementCount - index;
- if (numMoved > 0)
- System.arraycopy(elementData, index, elementData, index + numNew, numMoved);
- System.arraycopy(a, 0, elementData, index, numNew);
- elementCount += numNew;
- return numNew != 0;
- }
- //Returns whether two objects are equal.
- public synchronized boolean equals(Object o) {
- return super.equals(o);
- }
- //Calculating hash values
- public synchronized int hashCode() {
- return super.hashCode();
- }
- //Call toString() of the parent class
- public synchronized String toString() {
- return super.toString();
- }
- //Get a subset of fromIndex (including) to toIndex (excluding) in Vector.
- public synchronized List<E> subList(int fromIndex, int toIndex) {
- return Collections.synchronizedList(super.subList(fromIndex, toIndex), this);
- }
- //Delete elements from fromIndex to toIndex in Vector
- protected synchronized void removeRange(int fromIndex, int toIndex) {
- modCount++;
- int numMoved = elementCount - toIndex;
- System.arraycopy(elementData, toIndex, elementData, fromIndex,
- numMoved);
- // Let gc do its work
- int newElementCount = elementCount - (toIndex-fromIndex);
- while (elementCount != newElementCount)
- elementData[--elementCount] = null;
- }
- //Write function of java.io.Serializable
- private synchronized void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException {
- s.defaultWriteObject();
- }
- }
Summary
Vector's source code implementation is similar to ArrayList in general. The following summaries are given about Vector's source code:
Vector has four different construction methods. The capacity of the parametric construction method is the default value of 10, while the capacity-only construction method sets the capacity growth (the role of capacity growth can be seen from the source code, and the second point will be more detailed about capacity growth) as 0.
2. Pay attention to the method of capacity expansion to ensure Capacity Helper. Like ArrayList, Vector calls this method every time it adds elements (maybe one or a group) to ensure adequate capacity. When the capacity is not enough to accommodate the current number of elements, we first look at whether the parameter Capacity Increment is 0. If it is not 0, we set the new capacity as the capacity plus the capacity growth. If it is 0, we set the new capacity as twice the old capacity. If the new capacity is not enough, we set the new capacity as the input parameter directly. (that is, the required capacity) and then copy the elements to the new array using the Arrays.copyof() method as well.
3. Many methods add synchronized synchronized statements to ensure thread safety.
4. Similarly, in the method of finding the index value of a given element, the source code divides the value of the element into null and non-null cases, and the element is allowed to be null in Vector.5. Many other places are similar to ArrayList implementations, and Vector is now largely out of use.