Vector线程安全动态数组源码(jdk1.7)

准备知识

Vector集合实际上是实现了动态数组的方式,是可以随着向量元素的增加可以动态增长。实际上就是一种动态顺序表的应用。

属性

 // Object类型的数组,用来存储实际数据 
 protected Object[] elementData;  

说明:Vector底层实际存储数据的Object数组。

 // 代表向量中元素的个数 
 protected int elementCount;  

说明:Vector中elementData数组中存储元素的个数。

 /**  
  * 向量的增长因数  
  * 当向量的容量大于其容量时,向量的容量自动递增的量。  
  * 如果容量增量小于或等于零,则每次需要增长时,向量的容量增加一倍。  
  */  
 protected int capacityIncrement;

说明:Vector存储元素的容量大于其容量时,向量的容量自动递增的量。

构造方法

构造方法1:输入参数为初始化容量和增量参数的构造方法 。

  public Vector(int initialCapacity, int capacityIncrement) {  
      super();  
      // 如果向量初始化容量小于0,那么就报非法参数异常的错误。  
      if (initialCapacity < 0)  
          throw new IllegalArgumentException("Illegal Capacity: "+  
                                             initialCapacity);  
      // 将初始化容量的长度作为Object数组实际长度  
      this.elementData = new Object[initialCapacity];  
      // 初始化增量参数  
      this.capacityIncrement = capacityIncrement;  
  }  

构造方法2:使用指定的初始容量和等于零的容量增量构造一个空向量。

 public Vector(int initialCapacity) {  
     this(initialCapacity, 0);  
 }  

构造方法:构造一个初始化容量为10,增量为0的向量。

 public Vector() {  
     this(10);  
 }  

构造方法4:构造一个包含指定集合中的元素的向量,这些元素按其集合的迭代器返回元素的顺序排列。

   public Vector(Collection c) {  
        // 将集合Collection转化为Object数组elementData。如果c为空,那么就会报空指针异常  
       elementData = c.toArray();  
       elementCount = elementData.length;  
       // 将c中的元素拷贝到elementData中  
       if (elementData.getClass() != Object[].class)  
           elementData = Arrays.copyOf(elementData, elementCount, Object[].class);  
   }  

方法

ensureCapacity方法:扩充容量。

  public synchronized void ensureCapacity(int minCapacity) {  
      if (minCapacity > 0) {  
          modCount++;  
          ensureCapacityHelper(minCapacity);  
      }  
  }  

说明:如果指定的容量大于0,那么就进行扩容操作。

private void ensureCapacityHelper(int minCapacity) {  
       // minCapacity为实际向量中的元素需要的容量,如果minCapacity大于当前数组长度,那么就进行扩容  
       if (minCapacity - elementData.length > 0)  
           grow(minCapacity);  
   }  

说明:如果指定容量大于了当前Vector中固定elementData数组的容量,就进行真正的扩容。

   private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;  
  
   private void grow(int minCapacity) {  
       // oldCapacity旧容量是Object数组的长度  
       int oldCapacity = elementData.length;  
       // 如果增量capacityIncrement大于0,那么新容量为旧容量加上增量,否则为旧容量的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);  
   }

说明:如果capacityIncrement 增长因数大于0,那么扩容为原来的容量+capacityIncrement 。否则扩容为原来的2倍。

   private static int hugeCapacity(int minCapacity) {  
       // 如果实际需要的容量小于0就抛出异常  
       if (minCapacity < 0)   
           throw new OutOfMemoryError();  
       // 实际容量如果比最大容量还大,那么实际容量为Integer.MAX_VALUE,否则为Integer.MAX_VALUE - 8  
       return (minCapacity > MAX_ARRAY_SIZE) ?  
           Integer.MAX_VALUE :  
           MAX_ARRAY_SIZE;  
   }  

说明:如果扩容大于MAX_ARRAY_SIZE ,那么设置Integer.MAX_VALUE,否则设置为MAX_ARRAY_SIZE。


add方法:采用同步的方式往向量中添加元素e。

    public synchronized boolean add(E e) {  
        modCount++;  
        // 由于添加元素需要动态的扩容,所以调用ensureCapacityHelper方法,长度要增长1  
        ensureCapacityHelper(elementCount + 1);  
        // 这步采用顺序表添加元素的模板代码,赋值长度加1  
        elementData[elementCount++] = e;  
        return true;  
    }  

说明:如果elementCount + 1的容量大于数组的容量,将进行扩容;然后存储添加的值。


remove方法:删除指定下标的元素。

public synchronized E remove(int index) {
    // Vector的修改次数加1
    modCount++;
    // 如果下标大于元素数量,就抛出数组下标超过异常
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    // 使用下标获取对应的旧值
    E oldValue = elementData(index);
    // 计算删除元素后,需要移动补位的元素的数量
    int numMoved = elementCount - index - 1;
    // 如果需要的数量大于0,那么拷贝元素
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    // 删除元素
    elementData[--elementCount] = null; // Let gc do its work
    // 返回旧值
    return oldValue;
}

总结

1. Vector是线程安全的集合。
2. Vector可以存入null元素。
3. Vector可以存入重复元素。
4. Vector采用动态数组的方式实现的。
5. Vector默认的初始化容量为10,增量因子为0。
6. Vector扩容策略:如果Vector构造器中指定了增量因子capacityIncrement,那么Vector扩容为原容量+增量因子的大小。
如果未指定增量因子,那么Vector扩容为原来的2倍。

你可能感兴趣的:(Vector线程安全动态数组源码(jdk1.7))