Java集合源码分析<三>:Vector的源码分析
一、底层结构原理
Vector和ArrayList一样,底层都是通过数组实现,不同的是,Vector的方法都被synchronized关键修饰,包括迭代器,所以Vector是一个线程安全的集合,不过也正是这样,Vector的性能比较低,所以基本被弃用,替代它的是JUC下的并发集合类。Vector的源码实现逻辑ArrayList基本一致,所以源码分析中,只分析和ArrayList不同的地方。
二、构造方法
Vector的构造方法和ArrayList不同,在ArrayList创建对象的时候,未指定数组容量的情况下,并不会初始化数组长度为10,在第一次插入元素时才会初始化为10,而Vector会构造函数完成数组长度为10的操作,这也是为多线程访问效率考虑,源码如下:
// Vector.java 150行
public Vector(int initialCapacity) { this(initialCapacity, 0); } public Vector() { this(10); }
另外,Vector还可以构造方法中指定一个扩容时增长系数capacityIncrement,在指定扩容增长系数之后,Vector的扩容就会以此增长系数为准,这也是不同ArrayList的地方。
// Vector.java 133行
public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; // 初始化数组 this.capacityIncrement = capacityIncrement; // 扩容增量 }
三、扩容方法
Vector和ArrayList的的扩容方法在扩容增量上不同,ArrayList固定为原来的1.5倍,而Vector默认为2倍,如果指定了扩容增量,还以扩容增量为准进行扩容。
// Vector.java 260行
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; // 如果未指定扩容增量, 就是扩容为原来的2倍, 指定扩容增量就扩容增量为准 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); }
四、指定容量
Vector可以通过setSize()方法指定数组的长度,多出长度的元素会被置空
public synchronized void setSize(int newSize) { modCount++;//修改次数+1 if (newSize > elementCount) {//如果传进来的新size大小要大于当前的元素个数 ensureCapacityHelper(newSize);//则选择该值进行扩容操作 } else {//否则,也就是比它小的话 for (int i = newSize ; i < elementCount ; i++) { elementData[i] = null;//小于空出的后面的元素都将设置成null } } elementCount = newSize; }
四、和ArrayList对比
1、ArrayList线程不安全,性能更高,Vector线程安全,性能低
2、Vector默认扩容为原来的2倍,同时可以指定增长系数,ArrayList只能是1.5倍