扩容:
ArrayList,如果使用有参构造函来创建,先根据指定容量创建数组,后续以1.5倍进行扩容;如果使用无参构造函数来创建,第一次添加元素,扩容到10,后续也是以1.5倍进行扩容。
源码剖析
以无参方式创建ArrayList集合
-
public class Test1 { public static void main(String[] args) { //首先从无参的构造函数看起 ArrayList<String> list = new ArrayList<>(); list.add("6"); } }
-
ctrl点击后面的ArrayList<>();进入ArrayList类
public ArrayList() { //以无参构造函数创建ArrayList集合对象,将elementData赋值为有一个内容为空Object数组 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //elementData和DEFAULTCAPACITY_EMPTY_ELEMENTDATA在ArrayList中无参默认构造函数中的初始值
transient Object[] elementData; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
-
进入add(E e)方法
public boolean add(E e) { // 在添加数据前确保又能够操作的空间,且为扩容的条件,当size为elementDate的长度时,扩容条件满足 ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } private int size;//ArrayList的私有属性,初始值为0
-
进入ensureCapacityInternal(size + 1)
private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }
-
进入calculateCapacity(elementData, minCapacity)
//minCaoacity:1 elementData:空的Object数组 private static int calculateCapacity(Object[] elementData, int minCapacity) { //elementData之前被DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋过值,结果为ture if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //DEFAULT_CAPACITY = 10 ,静态常量 return Math.max(DEFAULT_CAPACITY, minCapacity); } //minCapacity = 10 return minCapacity; }
-
进入ensureExplicitCapacity(int minCapacity)
//minCapacity = 10 private void ensureExplicitCapacity(int minCapacity) { //记录从this对象创建以来,增删改查方法每执行一次,modCount都会++一次 modCount++; //elementData.length = 0 elementData为Object空容器数组 minCapacity = 10 if (minCapacity - elementData.length > 0) //核心扩容方法 grow(minCapacity); }
-
进入grow(minCapacity)
private void grow(int minCapacity) { // 记录旧的容器的大小 int oldCapacity = elementData.length; // 预计要扩容到的容量,为旧容器的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); //如果新的容器大小小于当前容器的大小,值被当前容器大小覆盖 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /* 数组有点特殊性,数组对象要额外存储数组元素长度在头部,少了这8个长度可能与此有关。 尝试分配大于 MAX_ARRAY_SIZE 长度的数组会导致 OOM (换句话说,超过了该虚拟机的数组长度限制)。 ,一 般用不到,就不做过多解释 */ if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 给elementDate扩容并将之前的值继承,大小为newCapacity.length() elementData = Arrays.copyOf(elementData, newCapacity);
-
返回add()
//e 即传入的参数 public boolean add(E e) { ensureCapacityInternal(size + 1); //执行此条语句,默认从0下标开始被e值覆盖 elementData[size++] = e; return true; }
有参方式创建ArrayList集合
-
有参方式创建arrayList集合
public class Demo1 { public static void main(String[] args) { ArrayList<String> arrayList = new ArrayList<>(20); arrayList.add("张三"); } }
-
进入有参方法
//initialCapacity 传入的参数 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { //这里是new了一个Object对象数组,并非DEFAULTCAPACITY_EMPTY_ELEMENTDATA覆盖 this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { //EMPTY_ELEMENTDATA 一个内容为空Object数组 this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity); } }
-
进入add(E e)方法
public boolean add(E e) { //private int size;-------ArrayList的私有属性,初始值为0 ensureCapacityInternal(size + 1); elementData[size++] = e; return true; }
-
进入ensureCapacityInternal(size + 1)
//minCapacity:1 private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }
-
进入calculateCapacity(elementData, minCapacity),有返回
//minCaoacity:1 elementData:空的Object数组 private static int calculateCapacity(Object[] elementData, int minCapacity) { //elementDate的地址是new的或被EMPTY_ELEMENTDATA这个空的Object[]覆盖,结果为false if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } //mincapacity = 1 return minCapacity; }
-
进入ensureExplicitCapacity(int minCapacity)
//minCapacity = 1 private void ensureExplicitCapacity(int minCapacity) { //记录从this对象创建以来,增删改查方法每执行一次,modCount都会++一次 modCount++; //elementData.length = 20,不进入grow()方法 if (minCapacity - elementData.length > 0) grow(minCapacity); }
-
返回add()
public boolean add(E e) { ensureCapacityInternal(size + 1); //执行此条语句,默认从0下标开始被e值覆盖 elementData[size++] = e; return true; }