目录
1.成员变量
//元素数组
Object[] elementData
//The size of the ArrayList (the number of elements it contains),就是集合中包含元素的数量
int size
//集合结构被修改的次数,其实就是集合新增,删除操作这个字段都会增加1.在调用迭代器操作时,则会检查这个值,如果发现已更改,抛出异常
int modCount = 0
如果我们创建集合的时候没有指定初始化大小,就会调用下面这个构造方法,如果我们只是创建集合,那么集合的数组长度就是0
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
如果创建集合,然后add一个数据,那么集合的数组长度就会设置成默认的长度,也就是10
2.add方法
我就看了我们常用的,就直接在集合末尾加入一个元素,他还有在某个索引位子加入一个元素的add方法.
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!! 扩容
elementData[size++] = e; //给数组末尾新增一个数据
return true;
}
2.1:扩容的代码
private void grow(int minCapacity) {
// overflow-conscious code
//minCapacity是我们创建集合设置的大小+1和默认集合大小10中最大的数值
int oldCapacity = elementData.length;
//新的容量是集合中数组长度的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新的容量小于minCapacity就设置新的容量=minCapacity,也就是要选择minCapacity和集合长度1.5倍中最大的那个.
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新的容量大于Integer最大-8也就是(2147483639)
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 不然就设置数据长度=新的容量,开始的时候因为数组长度是0,然后加1等于1小于10,所以新的容量就是10,
//这也就是为什么创建集合没有设置集合大小,第一次新增的时候设置集合大小是10的原因.
elementData = Arrays.copyOf(elementData, newCapacity);
}
//如果默认大小和我们集合中数组长度+1中最大的那个比2147483639还要大,那就返回集合大小是Integer的最大值,
//不然就是2147483639(Integer最大-8)
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
总结一下就是(jdk8)
这里面有一个需要注意的是集合中数组长度length不一定等于集合的大小size,集合中数组长度是指当前集合的数组能够放多少数据,集合的大小size指的是集合当前有多少数据.
扩容大小 : 如果原集合大小的1.5倍和默认大小10和size+1三个中的最大值是否大于integer的最大值-8
否 : 那么创建的就是这三个中最大的那个的大小的数组假设是resultCapacity。
是 : 就判断默认大小10和size+1中最大值是否大于integer最大值-8
是 : 就创建integer最大值的数组
否 : 则就是integer最大值-8大小的数组
if(集合中数组长度的1.5倍小于默认大小和集合中size+1中最大的那个 且 集合中数组长度的1.5倍小于Integer最大值-8){
最终集合大小就是默认大小和集合中size+1中最大的那个;
}
if(集合中数组长度的1.5倍小于默认大小和集合中size+1中最大的那个 且 集合中数组长度的1.5倍大于Integer最大值-8){
if(集合中数组长度的1.5倍大于Integer最大值-8){
if(默认大小和集合中size+1中最大的那个也大于Integer-8){
最终集合大小就是Integer的最大值;
}else{
最终集合大小就是Integer最大值-8;
}
}
}
if(集合中数组长度的1.5倍大于默认大小和集合中size+1中最大的那个 且 集合中数组长度的1.5倍小于Integer最大值-8){
最终集合大小就是集合中数组长度的1.5倍;
}
if(集合中数组长度的1.5倍大于默认大小和集合中size+1中最大的那个 且 集合中数组长度的1.5倍大于Integer最大值-8){
if(集合中数组长度的1.5倍大于Integer最大值-8){
if(默认大小和集合中size+1中最大的那个也大于Integer-8){
最终集合大小就是Integer的最大值;
}else{
最终集合大小就是Integer最大值-8;
}
}
}
2.2:将元素放到集合数组末尾中
elementData[size++] = e;
3:remove方法
public E remove(int index) {
//校验索引是否大于集合的大小size
rangeCheck(index);
//操作数量+1
modCount++;
//获取到该索引位子的数据
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
//相当于index后面的数据往前挪了一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//将最后一位设置成null,让gc回收
elementData[--size] = null; // clear to let GC do its work
//返回索引位子的数据
return oldValue;
}
System.arraycopy方法的定义