ArrayList 源码分析 基于jdk1.8:
1:数据结构:
transient Object[] elementData; //说明内部维护的数据结构是一个Object[] 数组
成员属性:
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {}; //空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //默认空数组
transient Object[] elementData; //维护数组的引用
private int size; //数组长度
2:构造方法:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //构造长度为0的Object[] 赋值给elementData,用于后面保存数据
}
3:主要方法的分析: add get remove add(int index,Object o)
1) add: 以添加第一个元素为例
public boolean add(E e) { e=”aa”
ensureCapacityInternal(size + 1); // size=0
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) { // minCapacity=1
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //第一个元素 true
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //取 DEFAULT_CAPACITY
}
ensureExplicitCapacity(minCapacity);
}
下面进入ensureExplicitCapacity 分析
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0) //10-0=10
grow(minCapacity); //进入扩容的方法
}
以下是扩容的方法:
private void grow(int minCapacity) { // minCapacity=10
// overflow-conscious code
int oldCapacity = elementData.length; // oldCapacity=0
int newCapacity = oldCapacity + (oldCapacity >> 1); //移位操作,移位后newCapacity=0
if (newCapacity - minCapacity < 0) //0-10=-10
newCapacity = minCapacity; // newCapacity=10
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); //将旧数组中的内容拷贝到新的数组中 并且将新的数组赋值给elementData
}
扩容机制:
int newCapacity = oldCapacity + (oldCapacity >> 1); //将新数组扩容为原先数组的1.5倍长度
2):add(int index,Object o)方法分析
主要的实现方法如下:
public void add(int index, E element) { // index1
rangeCheckForAdd(index); //和add方法里的一直
ensureCapacityInternal(size + 1); //和add方法里的一直
System.arraycopy(elementData, index, elementData, index + 1,
size - index); //主要是这里实现的index后面元素的拷贝
elementData[index] = element;
size++;
}
下面分析这句代码实现的效果
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
原始数组的结构和数据:
System.arraycopy方法执行后的数据结构 将 b2,b3 往后复制元素
最后将index处的元素赋值
elementData[index] = element;
这就是在具体索引进行add 的方法,往后的元素进行拷贝,导致消耗比较大
3):get方法:
public E get(int index) {
rangeCheck(index); //检查数组是否越界
return elementData(index); //返回数组的index 索引出的元素
}
Get 方法比较简单,就不做过多分析了