数组:效率高,但是其容量固定且无法动态改变。
ArrayList:容量可动态增长,但效率不如数组。
ArrayList定义:能够顺序的存储元素,可以存null值,动态的调整容量,对元素进行排序等一系列操作,线程不安全。
宏观说ArrayList是基于动态数组实现的。
构造函数:
private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;//默认的存储容量
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};//空元素数组
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
* DEFAULT_CAPACITY when the first element is added.
*
* Package private to allow access from java.util.Collections.
*/
transient Object[] elementData;//存储元素的数组,定义了transient在实现Serializable序列化是,不会被串行话
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;//ArrayList的元素数量 默认初始化为0,存在堆内存中,实际是ArrayList元素的个数
构造方法:
public ArrayList(int initialCapacity) {//构造一个含有初始容量的ArrayList
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];//初始化一个initialCapacity大小的数组
}
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
super();//默认创建10个大小数组
this.elementData = EMPTY_ELEMENTDATA;//将elementData的引用指向定义的空数组
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)//返回若不是Object[]将调用Arrays.copyOf方法将其转为Object[]
elementData = Arrays.copyOf(elementData, size, Object[].class);//扩容
}
动态增加容量
当添加元素的时候第一步就是先检查时候扩容,
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != EMPTY_ELEMENTDATA)
// any size if real element table
? 0
// larger than default for empty table. It's already supposed to be
// at default size.
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
//确认所需要的最小容量,在没有初始化的情况下,会使用默认容量为最小容量
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//如果确定要扩容,会修改modCount
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);//扩容
}
grow()方法
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//取到老的数组的长度
int newCapacity = oldCapacity + (oldCapacity >> 1);//计算新数组的长度,是原始的1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);//用计算出来的数组长度,往下传继续处理
}
copyOf()方法
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]//用新的长度创建一个新的数组
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,//把原数组里的元素拷进新数组里并返回
Math.min(original.length, newLength));
return copy;
}
总结:
在添加时候无论是add还是addAll,都是先判断时候要扩容,若果需要扩容,就复制数组,设置对应下标元素。
在扩容的时候,默认扩容一半,不够的话就用目标的size作为扩容后的容量。
在扩容后,修改modCount