ArrayList 源码探究(一) ArrayList容量
ArrayList实际维护的是一个名为ElementData的数组,ElementData.length为数组的实际容量(所占内存空间),ArrayList实例的size属性只是表征元素的数量。
ArrayList有两个构造函数,一个为无参数的构造函数,另一个是有参数的构造函数。
import java.util.ArrayList;
import java.util.Iterator;
public class 集合类 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*有参的构造函数*/
ArrayList<Integer> a = new ArrayList<Integer>(0);
System.out.println(a.size()); //输出0
System.out.println(a.get(0)); //抛出异常,因为数组为空
}
}
有参的构造函数源码
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) { //当参数大于0时,新建一个大小为参数的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) { //参数等于0时,数组为{} ,即为空
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
无参的构造函数源码
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
容量增长:
1:无参的构造方法
import java.lang.reflect.*;
import java.util.ArrayList;
public class 集合类 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ArrayList<Integer> a = new ArrayList<Integer>();// 调用无参构造方法
Field f1 = ArrayList.class.getDeclaredField("elementData"); //使用反射获取私有属性
f1.setAccessible(true);
Object[] elementData;
for(int i=0;i<50;i++){
a.add(i);
elementData = (Object[])f1.get(a);
System.out.print(elementData.length+"\\"); //不断添加元素的同时输出容量
}
}
}
输出为:10\10\10\10\10\10\10\10\10\10\15\15\15\15\15\22\22\22\22\22\22\22\33\33\33\33\33\33\33\33\33\33\33\49\49\49\49\49\49\49\49\49\49\49\49\49\49\49\49\73\ 容量变化10->15->22->33->49 每次扩充为原容量的1.5倍,在源码中也可以得到印证。
2 有参数的构造方法
import java.lang.reflect.*;
import java.util.ArrayList;
public class 集合类 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ArrayList<Integer> a = new ArrayList<Integer>(18);// 调用有参构造方法
Field f1 = ArrayList.class.getDeclaredField("elementData"); //使用反射获取私有属性
f1.setAccessible(true);
Object[] elementData;
for(int i=0;i<50;i++){
a.add(i);
elementData = (Object[])f1.get(a);
System.out.print(elementData.length+"\\"); //不断添加元素的同时输出容量
}
}
}
输出为:18\18\18\18\18\18\18\18\18\18\18\18\18\18\18\18\18\18\27\27\27\27\27\27\27\27\27\40\40\40\40\40\40\40\40\40\40\40\40\40\60\60\60\60\60\60\60\60\60\60\ 同样符合规律,在将超过容量时扩充为1.5倍