集合框架--Vector

110 阅读5分钟

1. 概述

基于数据实现,增删慢,查询快,线程安全。

Vector 的数据结构和 ArrayList 一样,都是基于数据实现的,不同的 Vector 支持线程同步,即同一时刻只允许一个线程对 Vector 进行写操作(新增、删除、修改),以保证多线程环境下数据的一致性,但需要频繁地对 Vector 实例进行加锁和释放锁操作,因此 Vector 的读写效率在整体上比 ArrayList 低。

Vector 是一个有序的集合容器,底层也是一个数组,它与 ArrayList 是很相似的。

Vector 与 ArrayList 区别:

  1. Vector 是线程安全的,ArrayList 是非线程安全的
  2. Vector 默认扩容是原来的 2倍,而 ArrayList 是原来的 1.5 倍数
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{}
  • 实现 List 接口,具有集合的基本操作,有序列表
  • 实现了 RandomAccess 接口,支持随机访问
  • 实现了 Cloneable 接口,支持克隆,实现该接口的类可以调用 clone 方法,否则会抛出异常
  • 实现了 Serializable 接口,支持序列化和反序列化

2. 成员变量

/**
 * 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
 */
// Vector 中实际存储元素的数量
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
 */
// 增量系数,表示每次扩容增加多少的容量,如果为 0 每次扩容为原来的 2 倍,大于 0 则每次数组容量增加这个数
protected int capacityIncrement;

3. 构造方法

/**
 * Constructs an empty vector so that its internal data array
 * has size {@code 10} and its standard capacity increment is
 * zero.
 */
// 无参构造方法,初始化容量10
public Vector() {
    this(10);
}
​
/**
 * Constructs an empty vector with the specified initial capacity and
 * with its capacity increment equal to zero.
 *
 * @param   initialCapacity   the initial capacity of the vector
 * @throws IllegalArgumentException if the specified initial capacity
 *         is negative
 */
// 构造一个具有指定初始容量的集合
public Vector(int initialCapacity) {
    // 第二个参数 0 为增长系数,默认为 0,该方法未来指定
    this(initialCapacity, 0);
}
​
/**
 * Constructs an empty vector with the specified initial capacity and
 * capacity increment.
 *
 * @param   initialCapacity     the initial capacity of the vector
 * @param   capacityIncrement   the amount by which the capacity is
 *                              increased when the vector overflows
 * @throws IllegalArgumentException if the specified initial capacity
 *         is negative
 */
// 构造一个具有指定初始容量和增长系数的集合
public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    // 根据指定容量创建数组
    this.elementData = new Object[initialCapacity];
    this.capacityIncrement = capacityIncrement;
}
​
/**
 * Constructs a vector containing the elements of the specified
 * collection, in the order they are returned by the collection's
 * iterator.
 *
 * @param c the collection whose elements are to be placed into this
 *       vector
 * @throws NullPointerException if the specified collection is null
 * @since   1.2
 */
// 构造一个包含指定元素的集合,按照集合迭代器返回的顺序。
public Vector(Collection<? extends E> c) {
    // 集合转换成数组
    Object[] a = c.toArray();
    // 实际存储的元素的容量
    elementCount = a.length;
    if (c.getClass() == ArrayList.class) {
        elementData = a;
    } else {
        // 将集合中的数据拷贝到底层数组中
        elementData = Arrays.copyOf(a, elementCount, Object[].class);
    }
}

4. 扩容机制

// 添加元素方法,这里与 ArrayList 的类似,只不过多了一个 synchronized 关键词进行修饰
public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}
// 确保容量
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;
    // 如果未指定增长系数则为0,容量扩容为原来的2倍,即 newCapacity = 10 + 10
    // 如果指定增长系数则扩大增长系数的容量
    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);
}

5. 常用方法

  1. 获得指定下标处的数据
public synchronized E get(int index) {
    // 索引合法性判断
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    return elementData(index);
}
  1. 删除元素
// 根据索引下标删除元素
public synchronized E remove(int index) {
    modCount++;
    // 下标合法性判断
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    // 得到待删除的值,用于返回
    E oldValue = elementData(index);
    // 计算需要移动的元素个数,假设 9 个元素,删除下标为 5的元素
    // numMoved = 9 - 5 - 1 = 3
    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;
}
// 根据值删除元素
public boolean remove(Object o) {
    return removeElement(o);
}
​
public synchronized boolean removeElement(Object obj) {
    modCount++;
    int i = indexOf(obj);
    if (i >= 0) {
        removeElementAt(i);
        return true;
    }
    return false;
}
// 遍历 elementData 数组,得到待删除元素的下标,未找到返回 -1
public int indexOf(Object o) {
    return indexOf(o, 0);
}
public synchronized int indexOf(Object o, int index) {
    if (o == null) {
        for (int i = index ; i < elementCount ; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = index ; i < elementCount ; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}
​
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 */
}
  1. 添加元素方法

    在集合末尾添加一个元素

public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1); // 扩容判断,上面已经介绍
    elementData[elementCount++] = e;
    return true;
}
  1. 修改元素值
// 根据索引下标修改数据元素
// @Param index 下标
// @Param element 元素值
public synchronized E set(int index, E element) {
    // 索引下标合法性判断
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    // 根据下标得到元素值,最后返回使用
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
E elementData(int index) {
    return (E) elementData[index];
}
  1. 调整数组容量(缩容)
// 将底层数组的容量改为实际存储的元素个数
public synchronized void trimToSize() {
    modCount++;
    // 容量大小
    int oldCapacity = elementData.length;
    // 实际存储的元素数量小于集合的容量
    if (elementCount < oldCapacity) {
        // 将 elementData 数组的前 elementCount 个元素重新赋值给 elementData 中
        elementData = Arrays.copyOf(elementData, elementCount);
    }
}

参考文献:

juejin.cn/post/708400…

juejin.cn/post/713531…