ArrayList 底层原理分析--扩容
ArrayList类的多态
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
AbstractList
AbstractList继承AbstractCollection,实现List接口,因此除了具有集合的方法属性外,还具有固定顺序,以及索引特征。
AbstractList源码中包含了四个类Itr ,ListItr,SubList,RandomAccessSubList,分别来支持迭代和获取子列表。
RandomAccess
这个是一个随机访问,所谓的随机访问就是访问集合里面随机一个元素。当然所有的集合都具有随机访问的功能,但是基于基本结构的不同,实现的速度不同。ArrayList基于数组实现,天然带下标,可以实现常量级的随机访问,复杂度为O(1)。
Cloneable
Cloneable 接口和普通的接口不同,他只是用于标记类的使用者了解克隆过程。
如果一个对象请求克隆, 但没有实现Cloneable接口, 就会生成一个CloneNotSupportedException异常。
Serializable
这是在程序中为了能直接以 Java 对象的形式进行保存,然后再重新得到该 Java 对象,这就是序列化能力Serializable。当然,并不是所有的类都需要序列化,一般来说当需要远程调用的时候就需要把类给序列化进行传输。
成员变量
序列化编号
private static final long serialVersionUID
ArrayList默认初始容量
private static final int DEFAULT_CAPACITY = 10;
用于空实例的共享空数组实例。
private static final Object[] EMPTY_ELEMENTDATA = {};
用于默认大小的空实例的共享空数组实例。将其与EMPTY_ELEMENTDATA区分开来,以知道添加第一个元素时要扩容多少。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
存储数组列表元素的数组缓冲区。数组列表的容量就是这个数组缓冲区的长度。任何带有elementData = = DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空数组列表在添加第一个元素时将被扩展为DEFAULT_CAPACITY。
transient Object[] elementData;
数组列表的大小(包含的元素数量)。
private int size;
构造方法
指定容量大小的
public ArrayList(int initialCapacity)
无参构造的
public ArrayList()
指定集合元素类型的
public ArrayList(Collection<? extends E> c)
扩容
重头戏,ArrayList自动扩容的原理
应该不难理解吧,新的容量等于就的容量的1.5倍,>>1是位运算,也就是除以二。
第一个判断是 检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量
第二个判断是 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) hugeCapacity()
方法来比较 minCapacity 和 MAX_ARRAY_SIZE, 如果minCapacity大于最大容量,则新容量则为Integer.MAX_VALUE
,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 Integer.MAX_VALUE - 8
其实这个判断主要是在数组非常大的时候,接近 2的31次方减1的时候。MAX_ARRAY_SIZE的值就是2的31次方减1。
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);}
其他的底层方法就略过了。