introduction
In the previous article, we learned about a set class ArrayList, One of its brothers today Vector.
Why is it his brother ? Because in terms of the structure of the container ,Vector It is ArrayList A replica of , It’s also an array based data structure , The difference is ,Vector Each of the methods has been added synchronized Modifier , It’s thread safe .
Class declaration
use idea open Vector Source code , It’s not hard to find out , Its class declaration follows ArrayList As like as two peas , It’s all inherited AbstractList, And it’s all done RandomAccess Interface , Traversal elements with for Loops are more efficient than iterators .
* @author Lee Boynton
* @author Jonathan Payne
* @see Collection
* @see LinkedList
* @since JDK1.0
*/
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
It’s worth noting that , From the perspective of notes ,Vector yes JDK1.0 The version introduced , The group that belongs to the oldest set class , and ArrayList yes 1.2 Just introduced , So ,Vector It’s brother ,ArrayList It’s little brother , ha-ha ~~~~
Basic variables and constructors
Basic variables
Vector There are four basic variables of , Namely :
- The underlying array
protected Object[] elementData;
- Number of array elements
protected int elementCount;
- Increased capacity size , If this value is less than or equal to 0, It will expand when it is expanded 2 times ,
capacityIncrement
- The maximum capacity
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
Constructors
// Create initial knowledge capacity as 10 Array of , Growth 0
public Vector() {
this(10);
}
// Create an array with variable capacity , The increase is 0
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
// Create an array with variable capacity , You can set the growth rate
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
// Create an array containing the specified collection
public Vector(Collection<? extends E> c) {
elementData = c.toArray();
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
I can see ,Vector Constructor and member variables of and ArrayList Be the same in essentials while differing in minor points .
Member method
Capacity expansion
Vector And ArrayList Although it’s very similar , But there are differences in the size of the expansion ,ArrayList The default size after expansion is the original capacity Of 1.5 times , and Vector It is to judge the growth rate first , If it’s a non positive number , Then expand it to the original 2 times , Take a look at how it’s expanded :
// Parameter is the minimum required capacity
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// If the growth is not greater than 0, Capacity for 2 Multiple size
// Generally, the containers created by default do not transfer growth , So the default is growth 0, That is to say, by default, the capacity will be expanded by twice
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
add to
Vector The method of adding is to add synchronized
Keywords , And detect capacity before adding , Judge whether to expand capacity :
// Add elements to the end of the array , synchronous
public synchronized boolean add(E e) {
modCount++;
// Detection capacity
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
// Detect the size of the capacity , Expand the length of the array
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
public void add(int index, E element) {
insertElementAt(element, index);
}
// Insert the element of the corresponding index
public synchronized void insertElementAt(E obj, int index) {
modCount++;
if (index > elementCount) {
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
ensureCapacityHelper(elementCount + 1);
// Before inserting elements , Move the elements after the index by one bit
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
}
public synchronized void addElement(E obj) {
modCount++;
// Make sure the capacity is adequate
ensureCapacityHelper(elementCount + 1);
// Set the data of the last element directly
elementData[elementCount++] = obj;
}
// Add the entire collection
public synchronized boolean addAll(Collection<? extends E> c) {
modCount++;
// Turn a collection into an array object
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityHelper(elementCount + numNew);
// Copy the collection elements directly to the back of the array
System.arraycopy(a, 0, elementData, elementCount, numNew);
elementCount += numNew;
return numNew != 0;
}
// Insert a collection at the corresponding index
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);
// Calculate how many elements to move
int numMoved = elementCount - index;
if (numMoved > 0)
// Move the element behind the insertion position so many times
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
// Copy element array
System.arraycopy(a, 0, elementData, index, numNew);
elementCount += numNew;
return numNew != 0;
}
Vector The code of adding method is not very complicated , Follow ArrayList equally , In essence, it’s all about inserting data into an array , The difference is , Methods are all added synchronized modification , therefore , Its addition methods are thread safe .
Other ways to manipulate elements are the same , I’m not going to list them all here , Because they all follow ArrayList almost , in addition ,Vector Than ArrayList There’s an iterative method
public Enumeration<E> elements() {
return new Enumeration<E>() {
int count = 0;
public boolean hasMoreElements() {
return count < elementCount;
}
public E nextElement() {
synchronized (Vector.this) {
if (count < elementCount) {
return elementData(count++);
}
}
throw new NoSuchElementException("Vector Enumeration");
}
};
}
Back to a Enumeration Interface object , It’s probably a container interface , Never used , Don’t say too much .
Vector contrast ArrayList
Last , To sum up Vector and ArrayList Contrast. .
The same thing :
-
The bottom layer is based on array structure , The default capacity is 10;
-
It’s all done RandomAccess Interface , Support random access ;
-
There are expansion mechanisms ;
difference :
-
Vector There are ways to do synchronization , Is thread safe , and ArrayList It’s not thread safe ;
-
Vector By default, the size after expansion is the original 2 times , and ArrayList yes 1.5 times ;
-
Vector Than ArrayList There’s an iterator Enumeration;
although Vector Comparison ArrayList We’ve done synchronization , But it also affects efficiency , Because every time you call a method, you get the lock , therefore , In general , If there is no requirement for thread safety of collections , Recommended ArrayList.