一、 ArrayList概述:  

    ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。

ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输, 实现了Cloneable接口,能被克隆。

1) 私有属性:

   ArrayList定义只定义类两个私有属性:

ArrayList是基于数组实现的,是一个动态数组,如下:其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。

transient Object[] elementData;

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




有个关键字需要解释:transient。  

  Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。

为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。

2)构造方法:构造一个包含指定collection的元素的列表,这些元素按照该collection的迭代器返回它们的顺序排列的。

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}

Collection解释:类集,是一组对象。类集的增加使得许多 java.util中的成员在结构和体系结构上发生根本的改变。它也扩展了包可以被应用的任务范围。(网上查的)

集合的构造方法和固定集合的大小

List arrayList = new ArrayList(4);

3) 调整数组容量ensureCapacity: 

添加元素的时候会先判定集合的容量大小,是否需要扩容

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

每当向数组中添加元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,

如果超出,数组将会进行扩容,以满足添加数据的需求。数组扩容通过一个公开的方法ensureCapacity(int minCapacity)来实现。

在实际添加大量元素前,我也可以使用ensureCapacity来手动增加ArrayList实例的容量,以减少递增式再分配的数量。


public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != EMPTY_ELEMENTDATA)
        // any size if real element table
        ? 0
        // larger than default for empty table. It's already supposed to be
        // at default size.
        : DEFAULT_CAPACITY;

    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}

数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。或者根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。

实例:

也就是说,当增加数据的时候,如果ArrayList的大小已经不满足需求时,那么就将数组变为原长度的1.5倍,之后的操作就是把老的数组拷到新的数组里面。例如,默认的数组大小是10,也就是说当我们

add

10个元素之后,再进行一次add时,就会发生自动扩容,数组长度由10变为了15具体情况如下所示:

总结:在用户向ArrayList追加对象时,Java总是要先计算容量(Capacity)是否适当,若容量不足则把原数组拷贝到以指定容量为长度创建的新数组内,并对原数组变量重新赋值,指向新数组。

在这同时,size进行自增1。在删除对象时,先使用拷贝方法把指定index后面的对象前移1位(如果 有的话),然后把空出来的位置置null,交给Junk收集器销毁,size自减1,即完成了。