前言
前面讲到ArrayList和LinkList, LinkList在程序中虽然不常见,但是和和Vector相比的话,那使用率说也是必要高的, Vector工作这几年来,我完全没有使用过,开发或是研习大牛的代码时,也很少见。堪称隐士。下面就让我们一起研究下这位隐士的生活
正文
变量
/**
* 存储向量组件的数组缓冲区。 向量的容量是这个数组缓冲区的长度,并且至少足够包含向量的所有元
* 素。
* Vector 中最后一个元素之后的任何数组元素都为空。
*/
//Vector和ArrayList都是用数组作为数据结构的, 所以猜想,相关的add, remove等操作应该时一样的
//原理, 通过System.copyOf来实现
protected Object[] elementData;
protected int elementCount;
/**
* 向量容量自动增加的量。
* 当它的大小变得大于它的容量时增加。 如果容量增量小于或等于零,容量
* 每次需要增长时,向量的大小都会增加一倍。
*/
protected int capacityIncrement;
构造方法
//指定数组的初始容量,和扩容向量
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
//指定数组的初始容量, 扩容向量默认为0,(当扩容向量为0时,那么每次扩容时,扩容的值一般是当
//前数组容量的2倍)
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
//默认初始容量是10
public Vector() {
this(10);
}
//初始容量为c的长度,
public Vector(Collection<? extends E> c) {
Object[] a = c.toArray();
elementCount = a.length;
//如果是ArrayLsit, 因为都是数组,所以可以直接赋值
if (c.getClass() == ArrayList.class) {
elementData = a;
} else { //使用arrays.copyOf来赋值
elementData = Arrays.copyOf(a, elementCount, Object[].class);
}
}
添加
//使用了synchronized同步关键字
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//扩容操作
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//和ArrayLsit的区别,如果capacityIncrement > 为 capacityIncrement ,否则
//否则为oldCapacity增加当前的一倍
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);
}
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
//固定下标插入
public void add(int index, E element) {
insertElementAt(element, index);
}
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 boolean addAll(Collection<? extends E> c) {
modCount++;
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityHelper(elementCount + numNew);
System.arraycopy(a, 0, elementData, elementCount, numNew);
elementCount += numNew;
return numNew != 0;
}
//中间插入
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;
}
通过添加,发现具体的实现原理和ArrayLsit是一样的,小区别就是扩容的增量。
最大的区别就是相关方法全部用synchronized关键字来修饰的,所以应该是线程安全的,但是性能就没有ArrayList好了, 为了验证自己的猜想,继续往下。
类的描述
发现自己好傻,我应该先看类的注释,和api文档的。这样去研究会更直观些,
Vector类实现了一个可生长的数组对象。像一个数组,它包含的组件可以使用整数索引访问。然而, Vector的大小可以根据需要增长或缩小以适应添加和删除已经创建了 Vector后物品。
每个向量试图优化维护capacity和capacityIncrement存储管理。capacity总是至少向量的大小一样大;它通常是更大,因为组件被添加到向量,向量的存储增加capacityIncrement大小的块。应用程序可以增加一个向量的能力之前插入大量的组件,这样可以减少增量重新分配的数量。
The iterators returned by this class's iterator和listIterator方法快速失败:如果向量结构修改创建迭代器后,任何时候以任何方式除非通过迭代器的remove或add方法,迭代器就会抛出一个ConcurrentModificationException。并发修改,因此,面对迭代器快速、清晰地失败,而不是冒着任意,不确定的行为在未来一个不确定的时间。返回的Enumerations elements方法不是很快失败。
注意,迭代器的快速失败行为不能得到保证,一般来说,不可能努力做出任何担保的存在不同步的并发修改。快速失败迭代器扔ConcurrentModificationException力所能及。因此,编写一个程序,这将是错误的依赖这个异常的正确性:迭代器的快速失败行为应该只用来检测错误。
Java 2平台v1.2,这个类实现List接口改造,使其 Java Collections Framework的一员。与新的集合实现,Vector是同步的。如果一个线程安全的实现不需要,建议使用ArrayList Vector。
看了Api文档的解释,充分的验证了上面的猜想,下一章的时候先看类的Api文档,在去验证
下面的相关的 remove等代码我就不一一例出来了,感兴趣的小伙伴可以去看源码,和ArrayLised的原理相同,只是加了synchronized关键字来修饰