回顾List的特点:
- 有序列表
- 元素可以重复
概述:
先看代码:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- 继承于AbstractList,实现了List接口,是一个长度可变的集合,提供了增删改查的功能。
- 实现了RandomAccess接口,可以对元素进行快速访问。
- 实现了Serializable接口,说明ArrayList可以被序列化。
- 实现了Cloneable接口,可以被复制。
- 允许null的存在,允许数据重复。
- 非线程安全的。
底层实现原理
1、实现:
Object数组
2、特点:
查询快、增删慢
容量
1、默认容量
- 使用无参构造器,默认容量为0,
- 使用有参构造器,容量为参数值。
2、扩容机制
add()的扩容机制
当容量不够时,自动进行扩容:
- 若原本容量为0,则首次扩容容量调整为10;
- 若原本容量不为0,新数组的容量调整为原来数组容量的1.5倍;
- 将老数组的数据复制一份到新数组。
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);
}
addAll()的扩容机制
在下次扩容容量和实际添加元素的个数之间取最大值。
- 当前没有元素,下次扩容应该是10个,添加三个元素,最终容量应该为10
- 当前10个元素,下次扩容应该是15个,添加六个元素,最终容量应该为16
添加元素
1、在指定位置添加元素
- 先复制一份数组到新数组;
- 判断有没有空间,若没有空间则需要进行扩容;
- 将指定位置的元素以及后面的元素统一向后移动一位;
- 在指定位置放入新的元素。
2、在数组末尾进行元素添加:
- 直接将数组的长度加一;
- 在末尾放入新元素。