基本介绍

Vector位于java.util包,于JDK1.0引入,对于List的实现接口,比ArrayList和LinkedList引入还要早,算是JDK的早期实现。Vector的底层也是通过数组实现。查看UML类图:
Vector.png
关于Vector的历史,源码中有一段介绍:

As of the Java 2 platform v1.2, this class was retrofitted to implement the List interface, making it a member of the Java Collections Framework. Unlike the new collection implementations, Vector is synchronized. If a thread-safe implementation is not needed, it is recommended to use ArrayList in place of Vector.

Vector的出现要早于集合框架,在JDK1.2开始,Vector被重构为List的实现类之一,成为集合框架的成员。与新的集合实现不同,Vector 是同步的。如果不需要线程安全实现,建议使用 ArrayList 代替 Vector。
然后在实际应用中,即使需要使用同步的List实现也很少再使用Vector,已经被Collections.SynchronizedList或者CopyOnWriteArrayList替代。

源码分析

构造方法

Vector中包含了三个重要的成员变量

  1. // 存储数据元素的Object类型数组
  2. protected Object[] elementData;
  3. // elementData实际拥有元素的大小
  4. protected int elementCount;
  5. // 当Vector的大小变得大于其容量时,自动扩充容量长度的值
  6. // 如果容量增量小于或等于零,则每次需要增长时,向量的容量都会增加一倍。
  7. protected int capacityIncrement;

查看构造方法源码

  1. // 无参构造,默认初始化长度为10
  2. public Vector() {
  3. this(10);
  4. }
  5. // 指定初始化长度的构造方法,默认自动增长长度为0
  6. public Vector(int initialCapacity) {
  7. this(initialCapacity, 0);
  8. }
  9. // 指定初始化长度及自动增长长度的构造方法
  10. public Vector(int initialCapacity, int capacityIncrement) {
  11. super();
  12. if (initialCapacity < 0)
  13. throw new IllegalArgumentException("Illegal Capacity: "+
  14. initialCapacity);
  15. this.elementData = new Object[initialCapacity];
  16. this.capacityIncrement = capacityIncrement;
  17. }

add

Vector使用的是数组结构实现,使用add方法直接添加元素,是在数组结尾设置,查看源码,整个方法快被关键字所synchronized修饰,因此是线程安全的,但是也损失了一部分性能。

  1. public synchronized boolean add(E e) {
  2. // 记录Vector修改的次数,继承自AbstractList抽象类
  3. modCount++;
  4. // 确保容量可以存放数据
  5. ensureCapacityHelper(elementCount + 1);
  6. // 将元素存储在当前elementCount递增1下标对应的位置
  7. elementData[elementCount++] = e;
  8. return true;
  9. }

接下来查看ensureCapacityHelper方法如何校验数组长度,以及进行扩容

  1. private void ensureCapacityHelper(int minCapacity) {
  2. // 如果传入的下标位置比当前elementData数组长度小,调用grow方法进行扩容
  3. if (minCapacity - elementData.length > 0)
  4. grow(minCapacity);
  5. }

查看grow方法源码

  1. private void grow(int minCapacity) {
  2. // 记录当前数组的长度为oldCapacity
  3. int oldCapacity = elementData.length;
  4. // 判断增长因子capacityIncrement是否大于0
  5. // 如果capacityIncrement>0,新的长度为oldCapacity+capacityIncrement
  6. // 如果capacityIncrement<=0,新的长度为oldCapacity+oldCapacity
  7. // 当第一次调用add方法时
  8. // oldCapacity=10,newCapacity=10+10=20,即第一次调用add时,Vector会扩容至两倍
  9. int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
  10. capacityIncrement : oldCapacity);
  11. if (newCapacity - minCapacity < 0)
  12. newCapacity = minCapacity;
  13. if (newCapacity - MAX_ARRAY_SIZE > 0)
  14. // 此处的hugeCapacity方法以及MAX_ARRAY_SIZE同ArrayList
  15. newCapacity = hugeCapacity(minCapacity);
  16. // 调用Arrays的copyOf方法,原理同ArrayList
  17. elementData = Arrays.copyOf(elementData, newCapacity);
  18. }
  • 与ArrayList中相同部分可参考:https://www.yuque.com/starsray/java/udywoi

    insertElementAt

    insertElementAt方法可以在指定位置插入元素,查看源码
    1. public synchronized void insertElementAt(E obj, int index) {
    2. modCount++;
    3. // 如果index值大于当前数组中元素的个数,抛出数组越界异常
    4. if (index > elementCount) {
    5. throw new ArrayIndexOutOfBoundsException(index
    6. + " > " + elementCount);
    7. }
    8. // 调用ensureCapacityHelper检查数组长度是否需要扩容
    9. ensureCapacityHelper(elementCount + 1);
    10. // 调用系统的arraycopy方法,并替换指定位置的元素
    11. System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
    12. // 设置数组下标index处为指定元素obj
    13. elementData[index] = obj;
    14. // 数组元素个数++
    15. elementCount++;
    16. }
    Vector中同样支持add方法在指定位置设置元素,其底层使用的仍是insertElementAt方法,查看源码
    1. public void add(int index, E element) {
    2. insertElementAt(element, index);
    3. }

    总结

    Vector在JDK1.0版本出现,在JDK1.2中作为List的实现类,并入到集合框架大家庭中。其底层实现是基于数组实现的,相比于ArrayList,Vector是线程安全的,二者的扩容机制有所不同。
    Vector是一种古老传统的List实现,基本上已经被淘汰,由于方法都是同步方法,因此执行效率比较低,与其他List成员相比,Vector的增长因子可以手动指定。