ArrayList源码学习(2)
两个空数组常量属性
在ArrayList源码学习(1)中详细描述了ArrayList的构造方法,但是并未对两个静态的空数组常量属性EMPTY_ELEMENTDATA
和 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
做说明,其实这两个属性,主要是为了在调用ArrayList对象的方法时,方便确定在创建当前对象时,调用了哪一种构造方法
如果
elementData
是DEFAULTCAPACITY_EMPTY_ELEMENTDATA
,则说明是调用了无参数的构造方法,所以初始容量是DEFAULT_CAPACITY
如果
elementData
是EMPTY_ELEMENTDATA
,说明是调用了有参数的构造方法,初始容量由构造方法的参数决定
添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
在创建了对象之后,就意味着我们可以用它在内存中存储数据,要往容器中添加数据,首先要确定顺序表中有足够的空间,而ensureCapacityInternal
方法就是检测顺序表的容量,此时的参数是size+1
,顺序表对象中元素个数为size
,如果要成功向顺序表中添加一个元素,就必须要确保elementData
的容量不得少于size+1
,是顺序表中elementData
的最小容量
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
首先判断 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
,表示当创建ArrayList
对象时,调用的是无参构造方法,并且此时的顺序表中并无数据,所以从DEFAULT_CAPACITY
和参数最小容量minCapacity
中获得最大值,进而确定一个明确的最小容量
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
ensureExplicitCapacity
明确了顺序表的最小容量,modCount
表示顺序表结构发生改变的次数,当顺序表的最小容量minCapacity
大于elementData
的长度时,对顺序表进行扩展。
private void grow(int minCapacity) {
//获取elementData的现有长度
int oldCapacity = elementData.length;
//获取当前长度的1.5倍作为新的容量
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新的容量小于最小容量,则以最小容量为新容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新的容量超过了最大容量,调用hugeCapacity进行容量检测
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//将elementData中的元素复制到长度为newCapacity的新数组中,并将结果赋值给elementData
elementData = Arrays.copyOf(elementData, newCapacity);
}
hugeCapacity
方法是为了确保扩展的长度不会超过int
类型的长度
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
当minCapacity < 0
,意味着扩展的容量已经超过了int
类型的最大值,此时抛出了内存溢出的错误。当最小容量大于顺序表最大容量,就以Integer.MAX_VALUE
为新容量,否则以MAX_ARRAY_SIZE
为新容量
推荐阅读
-
Java深入学习(2):并发队列
-
学习9.总结# 1.函数初识 # 2.函数的定义 # 3.函数的调用 # 4.函数的返回值 # 5.函数的参数
-
关于jQuery的源码学习
-
基于Struts2开发校园二手购物商城 源码 B
-
1+X证书学习日志——css 2D&过渡
-
jQuery插件FusionCharts绘制ScrollColumn2D图效果示例【附demo源码下载】
-
Python进阶_I/O进阶学习笔记_2.魔法函数
-
详解koa2学习中使用 async 、await、promise解决异步的问题
-
【C#】学习笔记(2)委托Delegate相关
-
asp.net abp模块化开发之通用树2:设计思路及源码解析