ArrayList源码分析
一、创建ArrayList对象
1.1 JDK7
ArrayList存储对象的底层使用的Object[] elementData存储对象的,创建ArrayList对象时,可以指定初始化elementData(数组长度)的容量initialCapacity,若未指定initialCapacity,则默认为10。若构造器的参数为Collection集合,则将Collection集合赋给elementData
ArrayList xxx = new ArrayList();
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;
//ArrayList底层定义了Object[]数组进行存储对象
private transient Object[] elementData;
private int size;
/**
* 根据initialCapacity初始化Object[]的大小
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//根据initialCapacity初始化Object[]的大小
this.elementData = new Object[initialCapacity];
}
//空参构造器调用有参构造器initialCapacity默认为10
public ArrayList() {
this(10);
}
/**
*有参Collection集合的构造器
*/
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)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
1.2 JDK8
二、添加元素
2.1 JDK7
/*
添加元素前调用ensureCapacityInternal(size + 1)判断ArrayList的有效元素个数
是否超过容量(数组长度)
如果超过了,调用 grow(minCapacity)进行扩容
如果没超过,直接加入Object[] elementData数组中
*/
//添加一个元素到集合最后
public boolean add(E e) {
// 判断ArrayList添加后的有效元素个数是否超过容量(数组长度)
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//在index插入一个元素
public void add(int index, E element) {
//判断index的合法性
rangeCheckForAdd(index);
// 判断ArrayList添加后的有效元素个数是否超过容量(数组长度)
ensureCapacityInternal(size + 1);
/*
数组复制,从elementData的第index个元素开始复制,复制到新的elementData中第index + 1
开始,一共复制size-index个元素
*/
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
//判断index的合法性
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// 判断ArrayList的有效元素个数是否超过容量(数组长度)
if (minCapacity - elementData.length > 0)
//扩充容量(创建一个长度更长的数组,进行数组复制)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新的长度=旧的长度+旧的长度右移1位(相当于除于2),即新长度为旧长度的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新的长度大于MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;(数组最大长度)
if (newCapacity - MAX_ARRAY_SIZE > 0)
//新的长度不能超过Integer.MAX_VALUE
newCapacity = hugeCapacity(minCapacity);
// 创建一个长度更长的数组,进行数组复制
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
/**
* minCapacity大于数组最大长度MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
* 返回Integer.MAX_VALUE,否则返回MAX_ARRAY_SIZE
* 新的长度不能超过Integer.MAX_VALUE
*/
return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;
}
所以,ArrayList的最大长度不能超过Integer的最大长度
添加Collection集合到ArrayList集合中
//在ArrayList集合最后添加Collection集合
public boolean addAll(Collection<? extends E> c) {
//集合转为数组
Object[] a = c.toArray();
int numNew = a.length;
// 判断ArrayList添加集合后的有效元素个数是否超过容量(数组长度)
ensureCapacityInternal(size + numNew);
/*
数组复制,从a的第0个元素开始复制,复制到新的elementData中第size(最后)
开始,一共复制numNew个元素
*/
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
2.2 JDK8
创建ArrayList对象
/**
* 默认的容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空的Object数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 默认的空的Object数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存储ArrayList元素的Object数组
*/
transient Object[] elementData;
/**
*根据initialCapacity初始化Object[]的大小
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//如果initialCapacity=0,把空的Object数组赋给elementData
this.elementData = EMPTY_ELEMENTDATA;
} else {
//initialCapacity小于0,不合法
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* 无参构造先让默认空的Object数组赋给elementData(JDK7直接创建长度10的Object数组)
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
添加元素
//给定默认容量为10
private static final int DEFAULT_CAPACITY = 10;
public boolean add(E e) {
//判断ArrayList添加后的有效元素个数是否超过容量(数组长度)
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//判断是否为第一次添加,如果是,给定elementData的默认长度为10(空参构造)
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//判断是否需要扩容(空参构造第一次添加一定会扩容)
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//扩容
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
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);
}
JDK7与JDK8的比较
- JDK7空参创建ArrayList对象,会实例化elementData数组,给定长度为10
- JDK8空参创建ArrayList对象,不会实例化elementData数组
- JDK7、JDK8有参构造都会实例化elementData数组,并给定传入的长度
- JDK7、JDK8 add添加元素时,会判断数组的容量是否足够,若不够,则扩容
- JDK8 在第一次添加元素(构造器没有创建elementData数组对象,容量为0),扩容,并给定初始容量10
- ArrayList最大存储元素不能超过Integer的最大值
- 扩容即创建一个长度更长的新的数组,并拷贝原来数组的元素,最后赋给elementData数组
建议:如果比较确定存储元素的个数,开发中使用带参的构造器(即不会频繁的扩容,浪费性能)