outline
After learning arrayList and LinkedList, we continue to learn Vector
Part 1 Introduction to Vector
Introduction to Vector
Vector is a vector queue, which is jdk1 Class added by version 0. It inherits from AbstractList and implements list, randomaccess and clonable interfaces.
Vector inherits AbstractList and implements List; Therefore, it is a queue that supports related functions such as addition, deletion, modification and traversal.
Vector implements RandmoAccess interface, which provides random access function. RandmoAccess is implemented by List in java to provide fast access for List. In vector, we can quickly obtain the element object through the element serial number; This is fast random access.
Vector implements the clonable interface, that is, the clone() function. It can be cloned.
Unlike ArrayList, operations in Vector are thread safe.
Constructor for Vector
Vector There are four constructors // Default constructor Vector() // Capacity is the default capacity size of the Vector. When the capacity increases due to increasing data, the capacity will double each time. Vector(int capacity) // Capacity is the default capacity of the Vector, and capacityincrease is the increment value each time the Vector capacity increases. Vector(int capacity, int capacityIncrement) // Create a Vector containing collection Vector(Collection<? extends E> collection)
Vector API
synchronized boolean add(E object) void add(int location, E object) synchronized boolean addAll(Collection<? extends E> collection) synchronized boolean addAll(int location, Collection<? extends E> collection) synchronized void addElement(E object) synchronized int capacity() void clear() synchronized Object clone() boolean contains(Object object) synchronized boolean containsAll(Collection<?> collection) synchronized void copyInto(Object[] elements) synchronized E elementAt(int location) Enumeration<E> elements() synchronized void ensureCapacity(int minimumCapacity) synchronized boolean equals(Object object) synchronized E firstElement() E get(int location) synchronized int hashCode() synchronized int indexOf(Object object, int location) int indexOf(Object object) synchronized void insertElementAt(E object, int location) synchronized boolean isEmpty() synchronized E lastElement() synchronized int lastIndexOf(Object object, int location) synchronized int lastIndexOf(Object object) synchronized E remove(int location) boolean remove(Object object) synchronized boolean removeAll(Collection<?> collection) synchronized void removeAllElements() synchronized boolean removeElement(Object object) synchronized void removeElementAt(int location) synchronized boolean retainAll(Collection<?> collection) synchronized E set(int location, E object) synchronized void setElementAt(E object, int location) synchronized void setSize(int length) synchronized int size() synchronized List<E> subList(int start, int end) synchronized <T> T[] toArray(T[] contents) synchronized Object[] toArray() synchronized String toString() synchronized void trimToSize()
Part 2 Vector data structure
Inheritance of Vector
java.lang.Object ↳ java.util.AbstractCollection<E> ↳ java.util.AbstractList<E> ↳ java.util.Vector<E> public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
The relationship between Vector and Collection is shown in the following figure:
The data structure of Vector is similar to that of ArrayList. It contains three member variables: elementData, elementCount and capacityIncrement.
(01) elementData is an "array of Object [] type", which saves the elements added to the Vector. elementData is a dynamic array. If the > size of the dynamic array is not specified when initializing the Vector, the default size of 10 is used. With the increase of elements in the Vector, the capacity of the Vector will also grow dynamically. capacityIncrement is the growth coefficient related to the capacity growth. For the specific growth mode, please refer to the ensureCapacity() function in the source code analysis.
(02) elementCount is the actual size of the dynamic array.
(03) capacityIncrement is the growth factor of dynamic array. If the size of capacityIncrement is specified when creating a Vector; Then, every time the dynamic array capacity in the Vector increases, the increased size is capacityIncrement.
Part 3 Vector source code analysis (based on JDK1.6.0_45)
In order to better understand the principle of Vector, the source code of Vector is analyzed below.
package java.util; public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { // An array that holds the data in the Vector protected Object[] elementData; // Quantity of actual data protected int elementCount; // Capacity growth factor protected int capacityIncrement; // Serial version number of Vector private static final long serialVersionUID = -2767605614048989439L; // Vector constructor. The default capacity is 10. public Vector() { this(10); } // Constructor that specifies the size of the Vector capacity public Vector(int initialCapacity) { this(initialCapacity, 0); } // Specifies the constructor for Vector 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 the capacity of initialCapacity this.elementData = new Object[initialCapacity]; // Set capacity growth factor this.capacityIncrement = capacityIncrement; } // Specifies the Vector constructor for the collection. public Vector(Collection<? extends E> c) { // Get the array of "set (c)" and assign it to elementData elementData = c.toArray(); // Set 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 the 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 = actual number of elements public synchronized void trimToSize() { modCount++; int oldCapacity = elementData.length; if (elementCount < oldCapacity) { elementData = Arrays.copyOf(elementData, elementCount); } } // Confirm the help function for Vector capacity private void ensureCapacityHelper(int minCapacity) { int oldCapacity = elementData.length; // When the capacity of the Vector is insufficient to accommodate all the current elements, increase the capacity. // If the capacity increment factor is > 0 (i.e. capacityIncrement > 0), the capacity will be increased // Otherwise, double the capacity. 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 the Vector. public synchronized void ensureCapacity(int minCapacity) { // Add the 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 greater than Vector capacity", adjust the size of the Vector. ensureCapacityHelper(newSize); } else { // If "newSize is less than / equal to Vector capacity", set the elements starting at the newSize position to null for (int i = newSize ; i < elementCount ; i++) { elementData[i] = null; } } elementCount = newSize; } // Returns the total capacity of the Vector 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; } // Judge whether the Vector is empty public synchronized boolean isEmpty() { return elementCount == 0; } // Return "Enumeration corresponding to all elements in Vector" public Enumeration<E> elements() { // Enumeration is implemented through anonymous classes return new Enumeration<E>() { int count = 0; // Does the next element exist public boolean hasMoreElements() { return count < elementCount; } // Get 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 objects (o) public boolean contains(Object o) { return indexOf(o, 0) >= 0; } // Find the element (o) backwards from the index position. // If found, the index value of the element is returned; Otherwise, - 1 is returned public synchronized int indexOf(Object o, int index) { if (o == null) { // If the lookup element is null, find the null element forward and return its corresponding sequence number for (int i = index ; i < elementCount ; i++) if (elementData[i]==null) return i; } else { // If the lookup element is not null, find the element forward and return its corresponding sequence number 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); } // Find element (o) from back to front. And returns the index of the element public synchronized int lastIndexOf(Object o) { return lastIndexOf(o, elementCount-1); } // Find element (o) from back to front. The starting position is the number from front to back; // If found, the "index value" of the element is returned; Otherwise, - 1 is returned. public synchronized int lastIndexOf(Object o, int index) { if (index >= elementCount) throw new IndexOutOfBoundsException(index + " >= "+ elementCount); if (o == null) { // If the lookup element is null, find the null element in reverse and return its corresponding sequence number for (int i = index; i >= 0; i--) if (elementData[i]==null) return i; } else { // If the lookup element is not null, find the element in reverse and return its corresponding sequence number for (int i = index; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } // Returns the element at the index position in the Vector. // If the index month is closed, an exception is thrown public synchronized E elementAt(int index) { if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } return (E)elementData[index]; } // Gets the first element in the Vector. // If it fails, an exception will be thrown! public synchronized E firstElement() { if (elementCount == 0) { throw new NoSuchElementException(); } return (E)elementData[0]; } // Gets the last element in the Vector. // If it fails, an exception will be thrown! public synchronized E lastElement() { if (elementCount == 0) { throw new NoSuchElementException(); } return (E)elementData[elementCount - 1]; } // Set the element value of the index position to obj public synchronized void setElementAt(E obj, int index) { if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } elementData[index] = obj; } // Delete element at 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 element (obj) at 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 the Vector public synchronized void addElement(E obj) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = obj; } // Find and delete the element obj in the Vector. // If successful, return true; Otherwise, false is returned. 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 the 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 the 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(); } } // Return Object array public synchronized Object[] toArray() { return Arrays.copyOf(elementData, elementCount); } // Returns the template array of Vector. The so-called template array, that is, T can be set to any data type public synchronized <T> T[] toArray(T[] a) { // If the size of array a < the number of elements of vector; // Create a new T [] array with the size of "number of elements of Vector" 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; // All elements of the Vector are copied to array a. System.arraycopy(elementData, 0, a, 0, elementCount); if (a.length > elementCount) a[elementCount] = null; return a; } // Gets 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 the index position 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 the Vector. public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } // Delete the element in the Vector o public boolean remove(Object o) { return removeElement(o); } // Add the element element at the index position public void add(int index, E element) { insertElementAt(element, index); } // Delete the element at 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 the Vector contains the set c public synchronized boolean containsAll(Collection<?> c) { return super.containsAll(c); } // Add set 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 the elements of set c to 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 not in set c" public synchronized boolean retainAll(Collection<?> c) { return super.retainAll(c); } // Starting at the index position, add the set c to the 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); } // DP Hash public synchronized int hashCode() { return super.hashCode(); } // Call the toString() of the parent class public synchronized String toString() { return super.toString(); } // Gets the subset from fromindex (included) to toindex (excluded) in the Vector public synchronized List<E> subList(int fromIndex, int toIndex) { return Collections.synchronizedList(super.subList(fromIndex, toIndex), this); } // Delete the elements from fromIndex to toIndex in the 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; } // java.io.Serializable write function private synchronized void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { s.defaultWriteObject(); } }
Summary:
(01) Vector actually saves data through an array. When we construct Vecotr; If the default constructor is used, the default capacity size of the Vector is 10.
(02) when the capacity of the Vector is insufficient to accommodate all elements, the capacity of the Vector will increase. If the capacity increase factor is > 0, increase the capacity value by "capacity increase factor"; Otherwise, double the capacity.
(03) the cloning function of vector is to clone all elements into an array.
Part 4 Vector traversal mode
Vector supports four traversal modes. It is recommended to use the following second method to traverse the vector because of efficiency problems.
(01) the first one is traversed by iterators. That is, traverse through the Iterator.
Integer value = null; int size = vec.size(); for (int i=0; i<size; i++) { value = (Integer)vec.get(i); }
(02) the second, random access, traverses through the index value.
Since Vector implements the RandomAccess interface, it supports random access to elements through index values.
Integer value = null; int size = vec.size(); for (int i=0; i<size; i++) { value = (Integer)vec.get(i); }
(03) the third, the other for loop. As follows:
Integer value = null; for (Integer integ:vec) { value = integ; }
(04) the fourth method is Enumeration traversal. As follows:
Integer value = null; Enumeration enu = vec.elements(); while (enu.hasMoreElements()) { value = (Integer)enu.nextElement(); }
The code to test the efficiency of these traversal methods is as follows:
import java.util.*; /* * @desc Vector Traversal mode and efficiency test program. * * @author skywang */ public class VectorRandomAccessTest { public static void main(String[] args) { Vector vec= new Vector(); for (int i=0; i<100000; i++) vec.add(i); iteratorThroughRandomAccess(vec) ; iteratorThroughIterator(vec) ; iteratorThroughFor2(vec) ; iteratorThroughEnumeration(vec) ; } private static void isRandomAccessSupported(List list) { if (list instanceof RandomAccess) { System.out.println("RandomAccess implemented!"); } else { System.out.println("RandomAccess not implemented!"); } } public static void iteratorThroughRandomAccess(List list) { long startTime; long endTime; startTime = System.currentTimeMillis(); for (int i=0; i<list.size(); i++) { list.get(i); } endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println("iteratorThroughRandomAccess: " + interval+" ms"); } public static void iteratorThroughIterator(List list) { long startTime; long endTime; startTime = System.currentTimeMillis(); for(Iterator iter = list.iterator(); iter.hasNext(); ) { iter.next(); } endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println("iteratorThroughIterator: " + interval+" ms"); } public static void iteratorThroughFor2(List list) { long startTime; long endTime; startTime = System.currentTimeMillis(); for(Object obj:list) ; endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println("iteratorThroughFor2: " + interval+" ms"); } public static void iteratorThroughEnumeration(Vector vec) { long startTime; long endTime; startTime = System.currentTimeMillis(); for(Enumeration enu = vec.elements(); enu.hasMoreElements(); ) { enu.nextElement(); } endTime = System.currentTimeMillis(); long interval = endTime - startTime; System.out.println("iteratorThroughEnumeration: " + interval+" ms"); } }
Operation results:
iteratorThroughRandomAccess: 6 ms iteratorThroughIterator: 9 ms iteratorThroughFor2: 8 ms iteratorThroughEnumeration: 7 ms
Summary: traversing Vector, random access using index is the fastest and iterator is the slowest.
Part 5 Vector example
Let's learn how to use Vector by example
import java.util.Vector; import java.util.List; import java.util.Iterator; import java.util.Enumeration; /** * @desc Vector Test functions: traversing Vector and common API s * * @author skywang */ public class VectorTest { public static void main(String[] args) { // New Vector Vector vec = new Vector(); // Add element vec.add("1"); vec.add("2"); vec.add("3"); vec.add("4"); vec.add("5"); // Set the first element to 100 vec.set(0, "100"); // Insert "500" into position 3 vec.add(2, "300"); System.out.println("vec:"+vec); // (sequential lookup) get an index of 100 System.out.println("vec.indexOf(100):"+vec.indexOf("100")); // (find in reverse order) get the index of 100 System.out.println("vec.lastIndexOf(100):"+vec.lastIndexOf("100")); // Get the first element System.out.println("vec.firstElement():"+vec.firstElement()); // Get the 3rd element System.out.println("vec.elementAt(2):"+vec.elementAt(2)); // Get the last element System.out.println("vec.lastElement():"+vec.lastElement()); // Gets the size of the Vector System.out.println("size:"+vec.size()); // Gets the total capacity of the Vector System.out.println("capacity:"+vec.capacity()); // Gets the "2nd" to "4th" elements of the vector System.out.println("vec 2 to 4:"+vec.subList(1, 4)); // Traverse Vector through Enumeration Enumeration enu = vec.elements(); while(enu.hasMoreElements()) System.out.println("nextElement():"+enu.nextElement()); Vector retainVec = new Vector(); retainVec.add("100"); retainVec.add("300"); // Gets the collection of elements contained in 'retainVec' in 'vec' System.out.println("vec.retain():"+vec.retainAll(retainVec)); System.out.println("vec:"+vec); // Get String array corresponding to vec String[] arr = (String[]) vec.toArray(new String[0]); for (String str:arr) System.out.println("str:"+str); // Empty Vector. clear() is the same as removeAllElements()! vec.clear(); // vec.removeAllElements(); // Judge whether the Vector is empty System.out.println("vec.isEmpty():"+vec.isEmpty()); } }
Operation results:
vec:[100, 2, 300, 3, 4, 5] vec.indexOf(100):0 vec.lastIndexOf(100):0 vec.firstElement():100 vec.elementAt(2):300 vec.lastElement():5 size:6 capacity:10 vec 2 to 4:[2, 300, 3] nextElement():100 nextElement():2 nextElement():300 nextElement():3 nextElement():4 nextElement():5 vec.retain():true vec:[100, 300] str:100 str:300 vec.isEmpty():true