黑马程序员技术交流社区
标题: 技术贴之ArrayList扩容JDK源码解析 [打印本页]
作者: 学习使我快乐1 时间: 2018-8-3 09:35
标题: 技术贴之ArrayList扩容JDK源码解析
ArrayList 是一个动态数组,它是线程不安全的,允许元素为null,特点有序可重复。
直接上自己撸的源码,命名为RideArrayList
public class RideArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
//Java的序列化机制
private static final long serialVersionUID = 8683452581122892189L;
//默认创建初始化容量为10;
private static final int DEFAULT_CAPACITY = 10;
//创建Object的空数组 (元素数据)
private static final Object[] EMPTY_ELEMENTDATA = {};
//默认构造函数里的Object空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//**************存储集合元素的底层实现:真正存放元素的数组
//实现Serializable序列化时,被tansient关键字修饰,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
transient Object[] elementData;
//当前元素数量
private int size;
有参构造函数(初始化容量)
public RideArrayList(int initialCapacity) {
//如果定义容量值大于0,元素数组创建Object数组,默认长度为initialCapacity
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) { //如果容量为0,将空Object数组赋值元素数组
this.elementData = EMPTY_ELEMENTDATA;
} else { //如果容量小于0,抛出抛出的异常表明向方法传递了一个不合法或不正确的参数的异常
throw new IllegalArgumentException("Illegal Capacity: " +
initialCapacity);
}
}
接下来是ArrayList底层数组扩容方式
//最大数组长度为 2的31方-1-8;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数
public void ensureCapacity(int minCapacity) {
//如果扩充容量参数大于数组的长度,并且数组不是空数组,初始化值小于等于10
if (minCapacity > elementData.length
&& !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
&& minCapacity <= DEFAULT_CAPACITY)) {
//如果确定要扩容,会修改modCount
modCount++;
grow(minCapacity);
}
}
//数组扩容,默认扩容1.5倍
private Object[] grow(int minCapacity) {
return elementData = Arrays.copyOf(elementData,
newCapacity(minCapacity));
}
//默认扩容,扩容当前集合长度+1
private Object[] grow() {
return grow(size + 1);
}
private int newCapacity(int minCapacity) {
// 旧容量为当前数组的长度
int oldCapacity = elementData.length;
//新的容量为旧容量的1.5倍(oldCapacity >> 1可以看做oldCapacity/2)
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity <= 0) { //扩容的容量较小,则返回扩容参数
//如果当前集合为空集合,返回Math.max(DEFAULT_CAPACITY, minCapacity)
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity < 0) // 如果扩容参数小于0,则报内存溢出错误
throw new OutOfMemoryError();
return minCapacity;
}
//如果新容量小于等于2的23次方-9,这返回新容量(原容量的1.5倍)
return (newCapacity - MAX_ARRAY_SIZE <= 0)
? newCapacity
: hugeCapacity(minCapacity);
}
//如果新容量过大,
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // 如果容量小于0,则报内存溢出溢出(个人认为只要其他线程修改容量值的情况下)
throw new OutOfMemoryError();
//如果容量大于2的23次方-9,则返回2的23次方-1,否则返回2的23次方-9
return (minCapacity > MAX_ARRAY_SIZE)
? Integer.MAX_VALUE
: MAX_ARRAY_SIZE;
}
以上内容仅个人解析参考,可能有许多解析不到位的地方,多多见谅
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |