ArrayList解析

  • 继承的类和实现的接口
  • 构造方法


继承的类和实现的接口

public class ArrayList<E>extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, Serializable

List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,但此类是线程不安全的而vector是线程安全的。)

每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。

扩容公式:新容量 = 旧容量/2 + 旧容量(底层是通过移位操作,右移一位相当于除以2)

构造方法

ArrayList(): 这里初始容量为 0,可能有人说是10,但别急,详细可下面源码
              
ArrayList(Collection<? extends E> c) :构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection
                                       的迭代器返回它们的顺序排列的。 
                                       
ArrayList(int initialCapacity) :构造一个具有指定初始容量的空列表。

源码
首先,定义一个elementData数组,用来存储ArrayList中的元素,从这个可以看出,ArrayList是底层是借组于数组来实现的。

transient Object[] elementData; // non-private to simplify nested class access

构造方法

public ArrayList(int initialCapacity) {  //指定初始容量,这个好理解
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
  
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray(); //将容器collection转化为数组
        if ((size = elementData.length) != 0) {   //如果数组非空
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)   //
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.,用一个空数组代替,这个空数组是已经定义好的
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

另外一个就是这里

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;  就是这里,这是一个数组名,它的定义如下
    }

它的数组是空的!

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

郁闷许久,来回看了几次后,发现关于 transient Object[] 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 == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.

transient Object[] elementData是一个存储ArrayList元素的数组缓冲区,ArrayList的容量是此数组缓冲区的长度,在添加第一个元素时,将自动扩展为DEFAULT_CAPACITY,而DEFAULT_CAPACITY的申明是:

private static final int DEFAULT_CAPACITY = 10;

再看一个add方法

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 添加一个元素时,调用函数
        elementData[size++] = e;
        return true;
    }
  private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
  private static int calculateCapacity(Object[] elementData, int minCapacity) { 
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//构造方法中已经初始化了,所以他们两个相等
            return Math.max(DEFAULT_CAPACITY, minCapacity); //返回10
        }
        return minCapacity;
    }

因此,我觉得是在加入第一个元素后,容量才为10的,当然,这只是我的看法,我也无法保证一定是对的,如果哪位道友,觉得理解有误的话,可以指出来,虚心学习,共同进步~