深入ArrayList()源码
jdk1.8
java.util;
扩容机制
新数组都将替代旧数组,旧数组作为垃圾被回收
- ArrayList() 会使用长度为零的数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
- ArrayList(int initialCapacity) 会使用指定容量的数组
private static final Object[] EMPTY_ELEMENTDATA = {};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) 会使用 c 的大小作为数组容量
private static final Object[] EMPTY_ELEMENTDATA = {};public ArrayList(Collection<? extends E> c) {Object[] a = c.toArray();if ((size = a.length) != 0) {if (c.getClass() == ArrayList.class) {elementData = a;} else {elementData = Arrays.copyOf(a, size, Object[].class);}} else {// replace with empty array.elementData = EMPTY_ELEMENTDATA;}}
- add(Object o) 首次扩容为 10,再次扩容为上次容量的 1.5 倍
底层:先右移动1位(>>1),再加上之前的容量
public boolean add(E e) {//确保内部容量ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;}
- addAll(Collection c) 没有元素时,扩容为 Math.max(10, 实际元素个数),有元素时为 Math.max(原容量 1.5 倍, 实际元素个数)
public boolean addAll(Collection<? extends E> c) {Object[] a = c.toArray();int numNew = a.length;ensureCapacityInternal(size + numNew); // Increments modCountSystem.arraycopy(a, 0, elementData, size, numNew);size += numNew;return numNew != 0;}
特点
- 基于数组,需要连续内存
- 随机访问快(指根据下标访问)
- 尾部插入、删除性能可以,其它部分插入、删除都会移动数据,因此性能会低
- 可以利用 cpu 缓存,局部性原理
深入解剖
实现接口RandomAccess
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{}
进入RandomAccess
public interface RandomAccess {
}
可以看出没有存在任何方法
实际上,RandomAccess是用于标志判断方法:
- 实现接口,List可以直接通过下标访问索引所对应的元素
- 没有实现接口,通过迭代器next()寻找对应的元素
所以说:随机访问快(指根据下标访问)