public class ArrayListextends AbstractList implements List , RandomAccess, Cloneable, java.io.Serializable { // 底层Object数组 private transient Object[] elementData; // 数组有效元素个数 private int size; // 指定大小构造器 public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } // 默认构造器 public ArrayList() { this(10); } 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); } // 添加元素 public boolean add(E e) { ensureCapacity(size + 1); elementData[size++] = e; return true; } // 数组扩容的关键方法 public void ensureCapacity(int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } } // get方法 public E get(int index) { RangeCheck(index); // 判断数组下标 return (E) elementData[index]; } // 直接使用索引下标获取 E elementData(int index) { return (E) elementData[index]; } ...... }
总结jdk1.6源码:
1)调用默认构造器时,就给默认大小是10;
2)每次新增元素当容量不够时,扩容新数组大小约为原数组大小的1.5倍(newCapacity = (oldCapacity * 3)/2 + 1)。
数组扩容原理图:
2、jdk1.7关键源码public class ArrayListextends AbstractList implements List , RandomAccess, Cloneable, java.io.Serializable { // 默认容量 private static final int DEFAULT_CAPACITY = 10; // 空数组 private static final Object[] EMPTY_ELEMENTDATA = {}; // 底层Object数组 private transient Object[] elementData; // 数组有效大小 private int size; // 默认构造器 public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; } // add方法 public boolean add(E e) { ensureCapacityInternal(size + 1); // 保证数组容量和扩容!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { // 第一次添加元素的时候,给数组赋予最小大小为10 if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } // 扩容 ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } // 数组最大大小 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 + (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); } // get方法 public E get(int index) { RangeCheck(index); // 判断数组下标 return (E) elementData[index]; } // 直接使用索引下标获取 E elementData(int index) { return (E) elementData[index]; } ...... }
总结jdk1.7源码:
1)调用默认构造器时,elementData数组是一个空数组{};
2)当第一次调用add方法添加元素时,才创建一个大小为10的数组;
3)每次新增元素当容量不够时,扩容新数组大小约为原数组大小的1.5倍(newCapacity = oldCapacity + (oldCapacity >> 1))。
数组扩容原理图:同 jdk1.6
3、jdk1.8关键源码public class ArrayListextends AbstractList implements List , RandomAccess, Cloneable, java.io.Serializable { // 默认初始大小 private static final int DEFAULT_CAPACITY = 10; // 空实例数组 private static final Object[] EMPTY_ELEMENTDATA = {}; // 默认大小的空实例数组 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 实际保存值的对象数组 transient Object[] elementData; // 实际对象元素个数 private int size; // 在jdk1.8中调用空构造器的时候,是默认空数组 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } // add 方法 public boolean add(E e) { ensureCapacityInternal(size + 1); // 确保数组容量和扩容,修改计数加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); } return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } // 数组最大容量 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 + (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); } // get方法 public E get(int index) { RangeCheck(index); // 判断数组下标 return (E) elementData[index]; } // 直接使用索引下标获取 E elementData(int index) { return (E) elementData[index]; } ...... }
总结jdk1.8源码:
1)调用默认构造器时,elementData数组是一个空数组{};
2)当第一次调用add方法添加元素时,才创建一个大小为10的数组;
3)每次新增元素当容量不够时,扩容新数组大小约为原数组大小的1.5倍(newCapacity = oldCapacity + (oldCapacity >> 1))。
(虽然jdk1.8和jdk1.7在add方法的源码上有细微区别,但是本质上是一样的)
数组扩容原理图:同 jdk1.6



