从源码的角度简单理解 ArrayList 特性 (jdk 1.7,1.8)

先来说说ArrayList:

1.ArrayList实际上是通过一个数组去保存数据的,当我们构造ArrayList时,数组是没有初始化容量的

2.当ArrayList 调用add方法的时候,会判断数据是否为空,如果为空,则初始化数组容量。长度为10.

3.ArrayList是线程不安全的。

4.当ArrayList容量不足以容纳全部元素时,ArrayList会自动扩张容量,新的容量 = 原始容量 + 原始容量 / 2(也就是自动扩容

5. ArrayList的克隆函数,即是将全部元素克隆到一个数组中.

好了下面我们把这4句还原回去源码中,这样就可以让我们加速记忆:

 

ArrayList实际上是通过一个数组去保存数据的,当我们构造ArrayList时,数组是没有初始化容量的。

从源码可以看出  

elementData 就是存储ArrayList的数组,从   DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};  可以看出 new ArrayList的时候是没有初始化的。
  transient Object[] elementData; // non-private to simplify nested class access

  private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};


  public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

当ArrayList 调用add方法的时候,会判断数据是否为空,如果为空,则初始化数组容量。长度为10.

当add方法进来后,会进入  ensureCapacityInternal 方法,然后再进入 calculateCapacity。然后判断当前数组为{},就会赋值

DEFAULT_CAPACITY 为初始化数组长度

 

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

private static final int DEFAULT_CAPACITY = 10;

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

private int size;


 

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        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);
     }
      return minCapacity;
    }

 

ArrayList是线程不安全的:

在源码中可以看出 add方法是没有用到锁,如果多线程的情况下,会到造成线程安全问题!

从源码的角度简单理解 ArrayList 特性 (jdk 1.7,1.8)

 

当ArrayList容量不足以容纳全部元素时,ArrayList会自动扩张容量,新的容量 = 原始容量 + 原始容量 / 2(也就是自动扩容)

从代码可以看出当  

minCapacity - elementData.length > 0 就调用 grow 方法。

minCapacity 当前要增加元素的位置,elementData.length 就是目前ArrayList 底层数组的容量,当

minCapacity  > elementData.length 时,就代表 ArrayList 容量不够 ,调用grow方法,实现自动扩容。

从源码的角度简单理解 ArrayList 特性 (jdk 1.7,1.8)

 

然后我们来看看grow方法的实现

int oldCapacity = elementData.length; 就是目前ArrayList的容量

重点就是  

oldCapacity >> 1    oldCapacity 向右移一位 就相当于 oldCapacity / 2  ,再加上本身。

所以

newCapacity   就是扩容后的数组容量大小

从源码的角度简单理解 ArrayList 特性 (jdk 1.7,1.8)

 ArrayList的克隆函数,即是将全部元素克隆到一个数组中

 

elementData = Arrays.copyOf(elementData, newCapacity); 这个就是把原始的数组克隆到另一个已经扩容过的数组上,具体代码就不贴了,大家不懂的话,可以自行百度下,这个API也是比较简单的

从源码的角度简单理解 ArrayList 特性 (jdk 1.7,1.8)