CH24-Vector
Vector 和 ArrayList 非常相似,底层都是基于数组的实现,支持动态扩容。支持通过索引访问,删除,添加元素。Vector 也继承自 AbstractList,也实现了 Collections 接口。与 ArrayList 不同的是,Vector 是线程安全的容器。他的添加删除等方法都是 synchronized。但是 Vector 也支持 fail-fast。
构造器
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 the specified initial capacity and
* with its capacity increment equal to zero.
*
* @param initialCapacity the initial capacity of the vector
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
/**
* Constructs an empty vector so that its internal data array
* has size {@code 10} and its standard capacity increment is
* zero.
*/
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
* @since 1.2
*/
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);
}
与ArrayList类似,Vector支持初始化时指定大小,默认初始化的情况下,是一个可以容纳10个元素的数组。(这一点与ArrayList不同,ArrayList默认初始化时是空的数组).
Vector添加,删除,访问元素
Vector支持向尾部添加元素,向指定位置添加元素,在向指定位置添加元素的时候需要移动。支持访问某个位置的元素,访问头部,尾部元素,支持删除某个位置的元素,删除指定元素(通过equals比较).
public synchronized E firstElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return elementData(0);
}
/**
* Returns the last component of the vector.
*
* @return the last component of the vector, i.e., the component at index
* <code>size() - 1</code>.
* @throws NoSuchElementException if this vector is empty
*/
public synchronized E lastElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return elementData(elementCount - 1);
}
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
return elementData(index);
}
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
return elementData(index);
}
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
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++;
}
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 */
}
Vector的扩容策略与ArrayList不同,ArrayList总是以1.5倍的大小来扩容,而Vector会支持用户在构造Vector时指定一个整形的incrementCapacity变量,每次在需要增加的时候,都会尽量增加指定的incrementCapacity的大小。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
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);
}
如果增加incrementCapacity大小还不能保证放得下所有的元素,那么就增加可以放得下所有元素的大小。如果在创建Vector的时候,没有指定initialCapacity大小,initialCapacity是0,这就会导致每次增加元素都会扩容。这是相当低效的。jdk文档里已不推荐使用Vector。大概这是原因之一。
Vector的序列化
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
final java.io.ObjectOutputStream.PutField fields = s.putFields();
final Object[] data;
synchronized (this) {
fields.put("capacityIncrement", capacityIncrement);
fields.put("elementCount", elementCount);
data = elementData.clone();
}
fields.put("elementData", data);
s.writeFields();
}
Vector的序列化似乎只提供了writeObject方法,奇怪的是,这里方法在序列化的时候首先clone了所有的元素,尽管这样做可以保证同步,但是实在不确定这种方法的效率.
Vector优化
尽管Vector的设计有一点缺点,但是Vector也尽量保证了删除元素的时候设置应用为null,来尽量保证GC。
public synchronized void removeAllElements() {
modCount++;
// Let gc do its work
for (int i = 0; i < elementCount; i++)
elementData[i] = null;
elementCount = 0;
}
在clean元素的时候,设置数组的所有元素为null.
Vector 的线程安全性
如我们之前贴的方法所示,add , remove , get等都有synchronized关键字来保证线程安全。而且,Vector的遍历也通过modCount保证了fail-fast. 这种简单加锁的机制,在高并发的情况下,肯定会带来效率的影响。因此,在高并发时,还是需要使用效率更好的容器。
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.