ArrayList做为java中经常使用的集合类型有哪些特色须要咱们了解呢?本文将基于jdk1.8源码来一步步列出ArrayList有哪些须要使人注意的要点。java
ArrayList继承实现关系以下图:数组
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
从该图咱们能够看出,ArrayList实现了RandmoAccess接口,RandmoAcess接口实现以下:dom
public interface RandomAccess { }
RandmoAccess接口中实际上并没有任何实现,该接口只是表示实现了该接口的类可以提供快速访问功能。this
ArrayList实现了RandmoAccess接口表明可以进行快速访问,而ArrayList的快速访问功能其实是靠数组实现的,下面是ArrayList中最重要的两个属性:code
//ArrayList实际存数据的地方 transient Object[] elementData; //ArrayList的大小 private int size;
下面咱们来看ArrayList的默认构造方法:继承
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
默认构造方法会将elementData属性赋为DEFAULTCAPACITY_EMPTY_ELEMENTDATA,其中DEFAULTCAPACITY_EMPTY_ELEMENTDATA属性是一个空数组接口
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
接下来咱们看ArrayList中的add和get方法:ci
public boolean add(E e) { //确认是否扩容 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public E get(int index) { //检查是否越界 rangeCheck(index); return elementData(index); }
能够看出Arraylist底层是经过数组来操做的。element
ArrayList使用默认构造器建立类时建立的是一个空的数组,那么ArrayList是如何可以使用add方法存数据的呢?咱们能够详细看看add方法中的ensureCapacityInternal方法源码:rem
private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //DEFAULT_CAPACITY常量数值是10 return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { //记录修改次数 modCount++; if (minCapacity - elementData.length > 0) //扩容方法 grow(minCapacity); }
从以上源码能够看出当ArrayList为一个空数组时,会赋予一个默认的扩容大小10,而后再进扩容方法里扩容ArrayList,所以ArrayList使用默认构造器初始化时,不会立马初始化数组大小,而是等待调用add方法后才会进行初始化,且初始化大小为10。
咱们能够查看ArrayList的grow方法来看看arrayList实际是如何扩容的:
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; //位运算1.5倍扩容 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //判断minCapacity是否超出最大整数值 newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
以上代码分为以下几个步骤: