import java.util.Arrays;
/**
* 源码分析
*/
public class ArrayListSourceCode {
//ArrayList 的大小(它包含的元素数量)
private int size;
//用于默认大小的空实例的共享空数组实例。我们将其与 EMPTY_ELEMENTDATA 区分开来,以了解添加第一个元素时要膨胀多少。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//ArrayList默认大小
private static final int DEFAULT_CAPACITY = 10;
//这是继承自AbstractList中的字段,这类似于乐观锁中的Version,如果多线程修改的时候,发现modCount与之前的不一样就会报错ConcurrentModificationException
protected transient int modCount = 0;
//TODO 真正存储ArrayList数据最底层的数组
transient Object[] elementData;
//数组最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//添加数据的方法
public boolean add(E e) {
ensureCapacityInternal(size + 1);//当前元素数量+1当作参数传进去
//检测完内部空间够用以后,就把当前
elementData[size++] = e;
return true;
}
//确保内部容量 minCapacity – 所需的最小容量
private void ensureCapacityInternal(int minCapacity) {
//if(当前元素数据==空数据){
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 最小容量 = 取出两值最大的值(初始容量,所需的最小容量);
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
//}
}
//到了这个地方 minCapacity 就是当前数组容量了
ensureExplicitCapacity(minCapacity);
}
//确保显式容量
private void ensureExplicitCapacity(int minCapacity) {
//修改ArrayList标识符
modCount++;
//if((当前容量+1)-ArrayList数据元素.长度>0) //这说明需要扩容了,list长度不够用了
if (minCapacity - elementData.length > 0)
//扩容方法
grow(minCapacity);
}
//扩容,第一次运行的时候会扩容,以后到达扩容阈值都会进行扩容
private void grow(int minCapacity) {
// 老容量 = 元素当前元素长度
int oldCapacity = elementData.length;
// 新容量 = 老容量 + (老容量右移一位)
int newCapacity = oldCapacity + (oldCapacity >> 1);
//if( 新容量 - 所需的最小容量 < 0 )
if (newCapacity - minCapacity < 0)
//新容量 = 所需的最小容量
newCapacity = minCapacity;
//if(新容量 - 数组容量最大值 > 0 )
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//一切都正常就扩容,这个方法虽然是复制,但也可以完成扩容,elementData原本可能是50大小,如果newCapacity是80的话,elementData大小就变成80了,后面30个全是空
elementData = Arrays.copyOf(elementData, newCapacity);
}
//返回Integer最大值,如果当前已经是Integer最大值了,再次添加数据就会抛出oom异常
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
}
import java.util.Arrays; /** * 源码分析 */ public class ArrayListSourceCode { //ArrayList 的大小(它包含的元素数量) private int size; //用于默认大小的空实例的共享空数组实例。我们将其与 EMPTY_ELEMENTDATA 区分开来,以了解添加第一个元素时要膨胀多少。 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //ArrayList默认大小 private static final int DEFAULT_CAPACITY = 10; //这是继承自AbstractList中的字段,这类似于乐观锁中的Version,如果多线程修改的时候,发现modCount与之前的不一样就会报错ConcurrentModificationException protected transient int modCount = 0; //TODO 真正存储ArrayList数据最底层的数组 transient Object[] elementData; //数组最大容量 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //添加数据的方法 public boolean add(E e) { ensureCapacityInternal(size + 1);//当前元素数量+1当作参数传进去 //检测完内部空间够用以后,就把当前 elementData[size++] = e; return true; } //确保内部容量 minCapacity – 所需的最小容量 private void ensureCapacityInternal(int minCapacity) { //if(当前元素数据==空数据){ if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 最小容量 = 取出两值最大的值(初始容量,所需的最小容量); minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //} } //到了这个地方 minCapacity 就是当前数组容量了 ensureExplicitCapacity(minCapacity); } //确保显式容量 private void ensureExplicitCapacity(int minCapacity) { //修改ArrayList标识符 modCount++; //if((当前容量+1)-ArrayList数据元素.长度>0) //这说明需要扩容了,list长度不够用了 if (minCapacity - elementData.length > 0) //扩容方法 grow(minCapacity); } //扩容,第一次运行的时候会扩容,以后到达扩容阈值都会进行扩容 private void grow(int minCapacity) { // 老容量 = 元素当前元素长度 int oldCapacity = elementData.length; // 新容量 = 老容量 + (老容量右移一位) int newCapacity = oldCapacity + (oldCapacity >> 1); //if( 新容量 - 所需的最小容量 < 0 ) if (newCapacity - minCapacity < 0) //新容量 = 所需的最小容量 newCapacity = minCapacity; //if(新容量 - 数组容量最大值 > 0 ) if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); //一切都正常就扩容,这个方法虽然是复制,但也可以完成扩容,elementData原本可能是50大小,如果newCapacity是80的话,elementData大小就变成80了,后面30个全是空 elementData = Arrays.copyOf(elementData, newCapacity); } //返回Integer最大值,如果当前已经是Integer最大值了,再次添加数据就会抛出oom异常 private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } }