JDK版本
jdk7的版本 jdk1.7.0_80
****jdk8的版本 1.8.0_131
ArrayList中的常量
-
int DEFAULT_CAPACITY = 10; 数组的默认长度
-
Object[] EMPTY_ELEMENTDATA = {}; 空数组
-
Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 默认大小的空数组
-
Object[] elementData; 存储ArrayList元素的数组
-
int size; ArrayList的长度
-
int modCount = 0; 数组结构改变的次数
-
int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 数组需要8位去储存数组的长度2^31。 尝试分配更大的数组可能导致OutOfMemoryError:请求的数组大小超过VM限制
JDK7中的ArrayList
初始化
初始化时,使用有参构造器就创建elementData数组。使用无参构造器时就默认为{}。相对于我的jdk版本,这个7和8几乎没有区别
有的说jdk7中创建ArrayList是类似于单例模式中的饿汉式。不管传不传initialCapacity,都会初始化,我就找了段代码,别说还真是
使用无参构造器创建ArrayList时,会以默认容量10调用有参构造器创建Object数组。
JDK8中的ArrayList
初始化
初始化时,如果传入的initialCapacity大于0,就创建elementData数组。没有或使用无参构造器时就默认为{}
add方法
JDK1.8和1.7中add方法无太大区别
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确认容量是否够用
elementData[size++] = e; // 存储数据
return true;
}
由于代码分布分散,不好截图,就直接描述
ensureCapacityInternal(size + 1) 方法先去判断elementData是否为{}(没有传入默认的数组长度,第一次调用add方法),就使用DEFAULT_CAPACITY初始化elementData,不为DEFAULTCAPACITY_EMPTY_ELEMENTDATA时就判断是否满足扩容条件,满足就扩容
if (minCapacity - elementData.length > 0) grow(minCapacity);
grow(int minCapacity)
- 新扩容的数组长度为之前的1.5倍
- 扩容后的数组不满足最小长度,就把最小长度赋值给新的数组长度
- Arrays.copy()方法。复制指定的数组,截断或填充空值到指定长度。底层最终调用的还是System.arraycopy();
System.arraycopy();
额外写一下这个方法。在ArrayList中remove、addAll方法中都有这个方法的存在。
static native void arraycopy(Object src,int srcPos, Object dest, int destPos,int length);
- src 源数组
- srcPos 原数组中的起始位置
- dest 目标数组
- destPos 目标数组中的其实位置
- length 要复制的源数组元素的数量
总结
jdk7(某些版本):初始化时,使用无参构造器创建ArrayList时,会以默认容量10调用有参构造器创建Object数组。当调用add方法导致底层elementData的数组容量不够,则扩容。默认情况下扩容为原来容量的1.5倍。同时将原有数组赋值到新的数组中
jdk8:初始化时,如果传入的initialCapacity大于0,就创建elementData数组。没有或使用无参构造器时就不创建数组,第一次调用add方法时,底层创建容量为10的数组。当调用add方法导致底层elementData的数组容量不够,则扩容。默认情况下扩容为原来容量的1.5倍。同时将原有数组赋值到新的数组中
jdk7和8的扩容方式几乎是一致的。
JDK7(某些版本)中的ArrayList的对象的创建方式就类似于单例模式中的饿汉式,jdk8中的创建方式就相当于懒汉式。延迟了数组的创建。节省内存。