Vector源码分析

Vector与ArrayList底层实现基本类似,底层都是用数组实现的,最大的不同是Vector是线程安全的。ArrayList源码分析请参考ArrayList源码分析

一、源码分析

基于jdk1.7源码

属性

    protected Object[] elementData;//用来存储元素
 
    protected int elementCount;//元素数量
 
    protected int capacityIncrement;//扩容增量,扩容时增加的容量大小。

Vector多了一个capacityIncrement属性。当Vector需要扩容时,增加的容量大小就是该值。

而ArrayList扩容时是扩充到原容量的1.5倍。

构造器

    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }
 
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }
 
    public Vector() {
        this(10);
    }
 
    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时可以指定初始容量initalCapacity,如果不指定则默认初始容量为10

Vector也可以在创建时指定扩容增量,如果不指定则为0。

add方法

    public synchronized boolean add(E e) {
        modCount++;
        //确定是否还有容量
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

实现与ArrayList差不多,最大区别是该方法进行了同步。继续往下跟代码。

    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;
        
        //扩容。指定了扩容增量,则增加该值。没指定,则扩容到原来的两倍
        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);
    }

整个过程基本与ArrayList一样,但是不同点是Vecotor扩容增加的容量大小。

如果Vector初始化时指定了扩容增量,则增加的容量值就是指定的扩容增量,否则,增加1倍容量,也就是扩容到原来的2倍。

get方法

    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
 
        return elementData(index);
    }

很简单,与ArrayList一样,也是先进行边界检查,再根据下标获取元素。

remove方法

    public synchronized E remove(int index) {
        modCount++;
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        E oldValue = elementData(index);
 
        int numMoved = elementCount - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--elementCount] = null; // Let gc do its work
 
        return oldValue;
    }

跟ArrayList实现差不多,不再赘述。

二、Vector和ArrayList的比较

1.扩容

Vector在创建时能够指定扩容增量,如果指定了该增量,当自动扩容时增加的容量就是该增量值。如果创建时没指定增量(或该值<=0),则扩容1倍,即容量变为原来的2倍。

ArrayList并没有提供能指定增量的构造方法,扩容0.5倍,即容量变为原来的1.5倍(具体参考ArrayList源码分析)

2.线程安全和效率

Vector的修改方法都是线程安全的,然而java.util.concurrent包中对容器提供了线程安全的实现版本,非线程安全时,可以用ArrayList来代替Vector,需要线程安全时可以使用Collections.synchronizedList(new ArrayList())和CopyOnWriteArrayList来替代,也就是说Vector被淘汰了。

ArrayList并不是线程安全的,因此相对来说,ArrayList比Vector效率要高一些。

原文地址:https://www.cnblogs.com/rouqinglangzi/p/10115612.html