Loading

Vector的原理和使用

一、前言

Vector的中文翻译是向量的意思,在平时使用的不比ArrayList和LinkedList多,但是我们有必要了解一下它的使用和实现。

二、Vector的继承关系

 我们看一下Vector的类继承关系。Vector的类继承关系和ArrayList是一样的,因此Vector的功能和ArrayList很相似。

 

 

三、定义Vector

3.1 Vector的属性定义

 Vector主要定义了三个属性。elementData用于存储数据;elementCount用来记录存储元素的数量;capacityIncrement表示向量的容量,注释上说当向量的数量大于容量时,容量值会增加一倍。

/**
     * The array buffer into which the components of the vector are
     * stored. The capacity of the vector is the length of this array buffer,
     * and is at least large enough to contain all the vector's elements.
     *
     * <p>Any array elements following the last element in the Vector are null.
     *
     * @serial
     */
    protected Object[] elementData;

    /**
     * The number of valid components in this {@code Vector} object.
     * Components {@code elementData[0]} through
     * {@code elementData[elementCount-1]} are the actual items.
     *
     * @serial
     */
    protected int elementCount;

    /**
     * The amount by which the capacity of the vector is automatically
     * incremented when its size becomes greater than its capacity.  If
     * the capacity increment is less than or equal to zero, the capacity
     * of the vector is doubled each time it needs to grow.
     *
     * @serial
     */
    protected int capacityIncrement;

3.2 Vector的构造函数

Vector提供了四个构造函数:

  • public Vector(int initialCapacity, int capacityIncrement)
  • public Vector(int initialCapacity)
  • public Vector()
  • public Vector(Collection<? extends E> c)

参数capacityincrement给定了每次扩充的扩充值。当capacityincrement为0的时候,则每次扩充一倍,利用这个功能可以优化存储。

// capacity是Vector的默认容量大小,capacityIncrement是每次Vector容量增加时的增量值。
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);
}
 

 

四、Vector的源码解析

先来看一下添加方法:

public synchronized void addElement(E obj) {
        modCount++;
//确保容量不超限制 ensureCapacityHelper(elementCount
+ 1); elementData[elementCount++] = obj; } private void ensureCapacityHelper(int minCapacity) { // 如果超过容量大小,进行扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); } //扩容逻辑和ArrayList相同 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); }

再来看一下移除某个位置元素的方法

public synchronized void removeElementAt(int index) {
        modCount++;
//判断位置是否越界
if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } else if (index < 0) { throw new ArrayIndexOutOfBoundsException(index); }
//得到要移除元素的位置
int j = elementCount - index - 1; if (j > 0) {
//移动元素 System.arraycopy(elementData, index
+ 1, elementData, index, j); } elementCount--; elementData[elementCount] = null; /* to let gc do its work */ }

移动逻辑很简单,与ArrayList也很相似,就不多加以介绍了。

五、Vector、ArrayList和LinkedList的对比

        LinkedList与Vector和ArrayList有本置的区别,LinkedList是基于双向链表实现的,而ArrayList和LinkedList是基于数组实现的。

        Vector与ArrayList的比较:

1、 Vector的实现逻辑与ArrayList十分相似,但需要注意的是Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比。

2、ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;

3、Vector可以设置capacityIncrement,而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。

谈谈不同容器类型适合的场景:

  Vector 和 ArrayList 作为动态数组,其内部元素以数组形式顺序存储的,内存为一连续的区域,所以非常适合随机访问的场合。除了尾部插入和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需要移动后续所有元素。数组大小固定,不适合动态存储,不方便动态添加。
  LinkedList 进行节点插入、删除却要高效得多,大小可变 ,内存可能是不连续内存,链式存储。但是只能通过顺次指针访问,查询效率低,随机访问性能则要比动态数组慢。
  因此,在应用开发中,如果事先可以估计到,应用操作是偏向于插入、删除,还是随机访问较多,就可以针对性的进行选择。

六、总结

本文对Vector类进行了介绍,并对比了ArrayList、Vector和LinkedList三者的不同并分析了他们的使用场景。接下来会对Map接口的实现进行分析,希望大家多多关注。

 

posted @ 2020-04-11 14:22  Charming-Boy  阅读(790)  评论(0编辑  收藏  举报