测试代码一个菜鸟的源码之路
1.new初始化
1.当new一个ArrayList对象时,去看下ArrayList的构造函数,发现它的代码是这样的:
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
而elementData
和DEFAULTCAPACITY_EMPTY_ELEMENTDATA
都是Object数组:
transient Object[] elementData; // non-private to simplify nested class access
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
为啥在初始化时,要指向这个数组,是为了避免我们反复的创建无用数组,所有新new出来的ArrayList底层数组都指向缓存在方法区里的Object[]数组。
2.add添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
首先会执行ensureCapacityInternal()
函数,看下这个函数
到这里我们发现执行了
Array.copyof()
函数,再看下这个函数的实现发现会调用
System.arraycopy
这个native方法,主要功能就是进行数组的拷贝,到目前是初始化了一个长度为10的数组,然后就到了下一步将数组的第一个元素赋值e,然后size加一,然后add就操作完成了。
3.size()求大小
这个size就是上一步的size,每添加一个元素都会加1,所以求大小只要把这个值返回就行
4.ArrayList扩容
上方说道,添加以一个元素的时候,会初始化一个长度为10的数组,那当长度超过10时,会进行什么操作呢?还是来看看add的源码
和上方一样,还是会进到
ensureCapacityInternal()
中,但传入的值会是11这一步,会进入循环,将
minCapacity
的值赋11,然后执行将其作为参数传入ensureExplicitCapacity()
这一步没区别,来看下一步
这是重点,首先将
oldCapacity + (oldCapacity >> 1)
值赋给newCapacity。>>是位运算,>>多少位=除以2的多少次方。这个意思就是每次超出数组大小都会扩大原来的1/2。然后后面就和前面一样,就不详细阐述了。
网友评论