ArrayList(部分内容摘取于:优秀参考文章)
【介绍】
ArrayList就是动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了动态的增加和减少元素,实现了ICollection和IList接口,灵活的设置数组的大小等好处
ArrayList封装了一系列操作,如增删改查,对比使用传统的数组方便了很多,因为java代码已经替我们写好了,我们直接用即可。
【使用】
一、构造方法:
(1)无参构造器:返回一个初始容量为0的空列表,扩容是在第一次add的时候进行的
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
(2)传入一个 int类型
的有参构造器:返回一个以你传入的参数作为初始容量的空列表
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
(3)构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray();
if ((size = a.length) != 0) {
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
二、常用方法:
以实现List接口为例:
【底层操作机制源码分析】
(1)ArrayList中维护了一个Object类型的数组 elementData
(2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次add,则扩容为10,如果后续再次需要扩容,则扩容为原容量的1.5倍(看源码,有移位操作)
(3)如果使用的是指定大小的构造器,则初始容量为指定的大小,如果后续需要扩容,则扩容为1.5倍。
ArrayList类的相关方法和属性:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
//无参构造器:elementData被赋值为一个空的对象数组
}
transient Object[] elementData; //transient(短暂的意思):对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。
private static final int DEFAULT_CAPACITY = 10; //字段意思:默认容量,值为10
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //就是一个空的对象数组
private int size; //初始值为0
无参构造器第一次 add:
public boolean add(E e) {
modCount++; //该字段表示list结构上被修改的次数
add(e, elementData, size);
return true;
}
private void add(E e, Object[] elementData, int s) {
//判断元素个数 size 是否等于数组elementData的长度,如果相等,则进行扩容操作
if (s == elementData.length) //s=size=初始值0;elementData数组一开始也是空数组,长度为0
elementData = grow();
elementData[s] = e; //将元素添加进数组中
size = s + 1; //添加完成后,size加1
}
private Object[] grow() {
return grow(size + 1); //传入size + 1 = 0+1 = 1
}
private Object[] grow(int minCapacity) { //最小容量为 1(size + 1)
int oldCapacity = elementData.length; //旧容量为空数组长度0
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //第一次add,这里都是fasle,进入else
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else { //返回一个新的对象数组给elementData,容量是DEFAULT_CAPACITY, minCapacity这两个的最大值,故第一次扩容,容量是10
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
无参构造器第十一次add:
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// assert oldLength >= 0
// assert minGrowth > 0
int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
if (newLength - MAX_ARRAY_LENGTH <= 0) {
return newLength;
}
return hugeLength(oldLength, minGrowth);
}
有参构造器:
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
注意使用有参构造器传入参数0和使用无参构造器的区别:
//它们的扩容机制不太一样
List list2 = new ArrayList(0); //this.elementData = EMPTY_ELEMENTDATA;
List list3 = new ArrayList(); //this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
扩容方法:(Arrays.copyOf()方法详解-jdk1.8)
return elementData = Arrays.copyOf(elementData, newCapacity);
modCount参数:
参考文章:https://blog.csdn.net/u012926924/article/details/50452411