ArrayList简介
ArrayList是一个动态数组,它的容量可以动态增长,默认容量是10,每次扩容都为原来容量的1.5倍 。 从如下类定义可以看到,它继承了AbstractList,并实现了List/RandomAccess/Cloneable/java.io.Serializable接口
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
1.继承AbstractList和实现List接口,使得ArrayList有了增删改和遍历数组的功能
2.实现RandomAccess接口,即可以随即访问List内的元素,区别于通过Interator迭代器访问
3 这里输入引用文本3.实现java.io.Serializable接口,即可以序列化。
ArrayList两个重要成员变量
1.elementData,是Object[]。Object类型数组里面保存着ArrayList的元素
/**
* Object[]数组,保存ArrayList数据
*/
transient Object[] elementData;
2.size,即ArrayList的实际大小
/**
* ArrayList的实际大小(即保存元素的个数)
*/
private int size;
3个构造器:ArrayList容量的初始化
1.默认构造器 public ArrayList()
2.指定容量的构造器 public ArrayList(int initialCapacity)
3.将其他集合转成ArrayList的构造器 public ArrayList(Collection extends E> c)
其中,默认构造器初始化容量大小为10
/**
* 默认构造函数,初始容量为10
*/
private static final int DEFAULT_CAPACITY = 10;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
ArrayList源码解析
两个扩容函数,根据 期望容量minCapacity 来扩大ArrayList容量
public void ensureCapacity(int minCapacity) {
/*
* 【minExpand 计算】若 elementData 不为默认大小的空Object[]数组,
* 那么minExpand就为0,否则 minExpand 为 DEFAULT_CAPACITY
*/
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;
/*
* 【minCapacity 与 minExpand 比较】当 “期望容量 > 最小可扩展容量” 时
* 根据 期望容量 去扩容。也就是说想要扩容, minCapacity 一定大于 minExpand
*/
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
private void ensureCapacityInternal(int minCapacity) {
/*
* 【确定minCapacity】若ArrayList是默认大小的空Object[]数组,则取
* minCapacity 和 DEFAULT_CAPACITY 中的最大值
*/
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 直接扩容。根据 期望容量 来扩大ArrayList容量
ensureExplicitCapacity(minCapacity);
}
ensureCapacity()与ensureCapacityInternal()的区别是:
1、前者不一定扩容,只有当minCapacity > minExpand 时扩容(有条件的调用ensureExplicitCapacity())。
2、后者一定扩容(直接调用ensureExplicitCapacity())
当向ArrayList增加元素的时候,判断ArrayList容量是否足够的函数ensureExplicitCapacity() 若 期望容量 > 可用容量,即原ArrayList的可用容量已经不够用了,则调用grow()函数来扩大ArrayList容量,容量大小为minCapacity
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // Increment!
// 若 期望容量 > ArrayList可用容量
if (minCapacity - elementData.length > 0)
// 调用grow()扩容
grow(minCapacity);
}
对于grow(),值得注意的是扩容后新容量的大小:基于原容量*3/2与 期望容量minCapacity大小比较。 若 *3/2 > minCapacity,新容量 = 原容量的3/2 若 *3/2 < minCapacity,新容量 = minCapacity 反正总的一个原则:取值比较大的就对了
???那么问题就来了,是否新容量可以无限大? 函数hugeCapacity()给出了答案,如下。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 【基于原容量定新容量,且一定执行】新容量 = 原容量*3/2
int newCapacity = oldCapacity + (oldCapacity >> 1);
/*
* 【newCapacity取大 (已经扩容一次了,*3/2)】若 (新容量 < 企图容量) ,
* 则 (新容量 = 企图容量),反正取最大就是了。PS:这次比较的是
* (*3/2)与 minCapacity,取大者
*/
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
/*
* 【上限,在合理范围内扩容】这个范围就是数组和整型值的范围,最大值为
* MAX_ARRAY_SIZE(上限) 和 Integer.MAX_VALUE(上限)。
* 若 (企图容量 > MAX_ARRAY_SIZE),那么说明 MAX_ARRAY_SIZE 不能满足
* 需求大小,则用 Integer.MAX_VALUE
*/
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 前面千辛万苦得到合适的 newCapacity 后,终于可以开始扩容了,调用 .copyOf()
elementData = Arrays.copyOf(elementData, newCapacity);
}
Integer.MAX_VALUE和 MAX_ARRAY_SIZE之间的关系,如下:
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
可见,Integer.MAX_VALUE > MAX_ARRAY_SIZE > 0,而 扩容后的新容量在(0,Integer.MAX_VALUE]的左开右闭区间内。
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}