JDK1.8ArrayList源码
数组是存储在内存中的一块逻辑上连续的内存,只有相同类型的数据才能放到数组中
构造方法
- 无参构造方法: 直接给elementData这个Object数组指向一个空数组.
- 带参构造方法: 如果参数大于0,就根据参数创建数组,参数为0则创建空数组,否则报错
- 带参构造方法: 将集合通过toArray()方法转换为数组传给当前的空的elementData数组,然后判断当前赋值后的数组长度,当不为0时,再判断该数组类型是否为Object类型,不是Object类型则拷贝到一个Object数组中去并赋值给elementData,如果数组长度为0,就赋值给一个空数组.
add()方法
- 该方法会将参数放到数组最后,同时第一句就是一个扩容的方法,其中的size表示的是当前数组中的元素个数;
- 扩容的时候会以当前数组的长度的1.5倍扩容,同时在扩容的时候会modCount+1,方便并发时候的线程安全;
- 当数组是空的,第一次插入数据的时候,会将数组扩容到10,当不是第一次插入的时候,当前元素个数+1(赋值为minCapacity) > 数组长度,就会进行扩容,扩容的时候,会让数组长度变为其1.5倍,然后去和当前元素个数+1比较,谁大就是谁,初始的时候由于数组长度是0,所以会扩容为默认值10;
- 第一句就是判断下标是否合法,第二句是判断是否需要扩容,第三句是复制数组,将index之后的所有元素向后移动一位,第四句是给指定下标赋值,因为移动元素之后,index下标放的还是原来的值,所以需要重新赋值给element,最后一句是++size,因为新添加了元素
remove()方法
- 通过下标remove元素: 会返回移除的元素,过程是先判断下标是否越界,然后移动后面的元素到index开始的位置来,同时让最后一个位置置为null,因为防止之前数组就是满的,移动之后原来的最后一个位置有可能是有值的.
- 移除指定元素: 先判断目标元素是否为空,如果为空就移除第一个null元素,不为空就移除指定位置元素就好了,方法都是找到其下标执行fastRemove方法,fastRemove方法也是通过整体移动元素,然后让最右边的元素置为null.
这里的一个错误
就是在遍历的时候,如果我们用list方法修改了list的元素,就会报错并发修改异常,因为modCount对不上了.
当我们使用迭代器遍历或者增强for循环遍历
的时候,在循环的过程中不能通过list删除元素,因为它会利用cas思想去比较modCount的值,如果通过list修改元素就会导致modCount与期望值不一样,就会报并发修改异常这个错,我们只能通过iterator的remove方法删除元素.
但是如果我们通过while循环或者for循环遍历就可以通过list的remove方法删除元素,因为它会在删除操作之后更新modCount
- 第一个方法就是判断modCount的值是否等于期望值的,后面的抛出并发修改异常的地儿我没整明白