返回
Vector剖析:揭开动态数组的底层奥秘
后端
2024-01-04 09:12:19
- Vector简介
Vector是Java集合框架中的一个动态数组,它允许你存储任意类型的对象。与普通数组不同的是,Vector可以自动扩容,这意味着当你往Vector中添加元素时,它会自动增加容量以容纳更多元素。
Vector是一个线程安全的集合类,这意味着它可以同时被多个线程访问而不会产生数据错乱。这使得Vector非常适合在多线程环境中使用。
Vector的特点包括:
- 动态数组:Vector可以自动扩容,以容纳更多元素。
- 线程安全:Vector可以同时被多个线程访问而不会产生数据错乱。
- 继承自AbstractList:Vector继承自AbstractList,这意味着它提供了List接口的所有方法。
2. Vector的实现
Vector的底层实现是一个数组,这个数组被称为elementData。当Vector需要存储更多元素时,它会自动创建一个更大的数组,并将元素从旧数组复制到新数组中。
Vector的容量(capacity)是指它可以容纳的最大元素数量。当Vector的容量不够时,它会自动扩容,扩容后容量会增加一倍。
Vector的扩容操作可能会导致性能下降,因此,在使用Vector时,应该尽量预估需要存储的元素数量,并将其容量设置为一个合理的值。
3. Vector的源码分析
public class Vector<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable {
/**
* The array buffer into which the elements of the Vector are stored.
* The capacity of the Vector is the length of this array buffer.
*/
protected transient Object[] elementData;
/**
* The number of valid components in the Vector.
*/
protected int elementCount;
/**
* The amount by which the capacity of the Vector is automatically
* incremented when its size becomes greater than its capacity.
*/
protected int capacityIncrement;
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -2767605554748270744L;
/**
* Constructs an empty vector with the specified initial capacity and
* capacity increment.
*
* @param initialCapacity the initial capacity of the vector
* @param capacityIncrement the amount by which the capacity of the vector
* is automatically incremented when its size becomes
* greater than its capacity
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
/**
* Constructs an empty vector with an initial capacity of 10.
*/
public Vector() {
this(10);
}
/**
* Constructs a vector containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this
* vector
* @throws NullPointerException if the specified collection is null
*/
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);
}
/**
* Trims the capacity of this Vector to be the current size.
* If the capacity is larger than the size, then the capacity is changed
* to be equal to the size.
*
* This method is useful when you know that the Vector will no longer grow
* and you want to conserve space.
*/
public synchronized void trimToSize() {
modCount++;
if (elementCount < elementData.length) {
elementData = Arrays.copyOf(elementData, elementCount);
}
}
/**
* Returns the current capacity of this Vector.
*
* @return the current capacity of this Vector
*/
public synchronized int capacity() {
return elementData.length;
}
/**
* Increases the capacity of this Vector, if necessary, to ensure
* that it can hold at least the number of elements specified by
* the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public synchronized void ensureCapacity(int minCapacity) {
modCount++;
if (minCapacity > elementData.length) {
elementData = Arrays.copyOf(elementData,
Math.max(minCapacity, elementCount + capacityIncrement));
}
}
/**
* Sets the capacity of this Vector to the specified number of elements.
* If the new capacity is less than the current capacity, then the capacity
* is not changed.
*
* @param newCapacity the new capacity of this Vector
* @throws IllegalArgumentException if the new capacity is less than the
* current size of this Vector
* @since 1.2
*/
public synchronized void setSize(int newCapacity) {
modCount++;
if (newCapacity > elementCount) {
elementData = Arrays.copyOf(elementData, newCapacity);
} else {
if (newCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
newCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
elementCount = newCapacity;
}
}
/**
* Copies the components of this Vector into the specified array. The
* array must be big enough to hold all of the elements of this Vector.
*
* @param anArray the array into which the components get copied
* @throws NullPointerException if the specified array is null
* @throws IndexOutOfBoundsException if the specified array is not large
* enough to hold all of the elements of this Vector
* @since 1.2
*/
public synchronized void copyInto(Object[] anArray) {
System.arraycopy(elementData, 0, anArray, 0, elementCount);
}
/**
* Returns an array containing all of the elements in this Vector. The
* returned array will be safe to modify without affecting this Vector.
*
* @since 1.2
*/
public synchronized Object[] toArray() {
return Arrays.copyOf(elementData, elementCount);
}
// Most Stack methods are not implemented, but must appear in the class
/**
* Pushes an element onto the stack represented by this Vector.
*
* @param o the element to be pushed onto the stack
* @return the argument passed in
* @see Vector#pop
* @since 1.0
*/
public synchronized E push(E o) {
addElement(o);
return o;
}
/**
* Removes the object at the top of the stack represented by this Vector.
*
* @return The object at the top of the stack
* @see Vector#push
* @since 1.0
*/
public synchronized E pop() {
E obj;
int len = elementCount - 1;
if (len < 0) {
throw new EmptyStackException();
}
obj = elementData[len];
elementData[len] = null; // Eliminate obsolete reference
elementCount--;
return obj;
}
/**
* Returns the object at the top of the stack represented by this Vector.
*
* @return the object at the top of the stack
* @see Vector#pop
* @since 1.0
*/
public synchronized E peek() {
int len = elementCount - 1;
if (