同步容器类——1——ArrayList和vector

区别与联系
1.Vector是线程安全的集合类,ArrayList并不是线程安全的类。Vector类对集合的元素操作时都加了synchronized,保证线程安全。

2.Vector与ArrayList本质上都是一个Object[] 数组,ArrayList提供了size属性,Vector提供了elementCount属性,他们的作用是记录集合内有效元素的个数。与我们平常调用的arrayList.size()和vector.size()一样返回的集合内有效元素的个数。

3.Vector与ArrayList的扩容并不一样,Vector默认扩容是增长一倍的容量,Arraylist是增长50%的容量。

4.Vector与ArrayList的remove,add(index,obj)方法都会导致内部数组进行数据拷贝的操作,这样在大数据量时,可能会影响效率。

5.Vector与ArrayList的add(obj)方法,如果新增的有效元素个数超过数组本身的长度,都会导致数组进行扩容。
先看下他们的源码是怎么定义内部数据存储的:

private static final long serialVersionUID = 8683452581122892189L;

    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
     * DEFAULT_CAPACITY when the first element is added.
     */
    private transient Object[] elementData;

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

这是ArrayList的定义,他首先定义了他的初始化容量为10

private static final int DEFAULT_CAPACITY = 10

这里应该看到了数据存储是放在Object数组里的

private transient Object[] elementData

定义了数据的长度size

The size of the ArrayList (the number of elements it contains)

再看看Vector的定义:

/**
     * 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;

Vector定义了数组

protected Object[] elementData;

有效元素个数

protected int elementCount

Vector增长容量,默认0

protected int capacityIncrement

Vector和ArrayList在元素超过初始大小时扩容是不一样的
Vector中的元素个数超过了初始化容量的话,默认会增长一倍,请看代码:

/**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    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);
    }

而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;
}

/**
 * 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) {
    this(initialCapacity, 0);
}

/**
 * Constructs an empty vector so that its internal data array
 * has size {@code 10} and its standard capacity increment is
 * zero.
 */
public Vector() {
    this(10);
}

可以看到在构造函数中已经表明,可以指定其增量的大小,如果没有指定默认0。数组的初始化大小为10。
但是ArrayList就不可以进行增量的修改指定。还是看代码:

/**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);  //看这里
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

首先在构造函数中,ArrayList就没有提供相应的设置增量的方法,而扩容方法grow中直接就对数组进行增量50%的操作了,并没有相应的参数设置或判断增量的大小。

在上边都提到了一个静态常量是private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

这个常量是数组扩容的最大长度,但是为什么-8呢我看了上边的描述,感觉应该是:

Some VMs reserve some header words in an array.

有些虚拟机会在数组头部加入一些信息,如果还是设置最大的话,可能会导致OOM

这就是Vector和ArrayList在扩容及成员变量方面的区别及联系了。

猜你喜欢

转载自blog.csdn.net/qq_39411208/article/details/88067162