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