当 要 add 进第1个元素时,minCapacity为(size+1=0+1=)1
在Math.max()方法比较后,minCapacity 为10
然后紧接着调用ensureExplicitCapacity更新modCount的值
并判断是否需要扩容
oldCapacity为旧数组的容量
newCapacity为新数组的容量(oldCap+oldCap/2:即更新为旧容量的1.5倍)
检查新容量的大小是否小于最小需要容量,如果小于那就将最小容量置为数组的新容量
如果新容量大于MAX_ARRAY_SIZE,使用hugeCapacity比较二者
hugeCapacity逻辑:
对minCapacity和MAX_ARRAY_SIZE进行比较
若minCapacity大,将Integer.MAX_VALUE作为新数组的大小
若MAX_ARRAY_SIZE大,将MAX_ARRAY_SIZE作为新数组的大小
MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
add方法执行流程总结
- 这是第一次调用add方法的过程,当扩容值capacity为10之后,
- 继续添加第2个元素(先注意调用ensureCapacityInternal方法传递的参数为size+1=1+1=2)
- 在ensureCapacityInternal方法中,elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA不成立,所以直接执行ensureExplicitCapacity方法
- ensureExplicitCapacity方法中minCapacity为刚刚传递的2,所以第二个if判断(2-10=-8)不会成立,即newCapacity 不比 MAX_ARRAY_SIZE大,则不会进入 grow 方法。数组容量为10,add方法中 return true,size增为1。
- 假设又添加3、4......10个元素(其中过程类似,但是不会执行grow扩容方法)
- 当add第11个元素时候,会进入grow方法时,计算newCapacity为15,比minCapacity(为10+1=11)大,第一个if判断不成立。新容量没有大于数组最大size,不会进入hugeCapacity方法。数组容量扩为15,add方法中return true,size增为11
add(int index,E element)方法
add(int index, E element)方法(在元素序列指定位置(假设该位置合理)插入)的过程大概是下面这些
- 检测数组是否有足够的空间(这里的实现和上面的)
- 将 index 及其之后的所有元素向后移一位
- 将新元素插入至 index 处.
- 将新元素插入至序列指定位置,需要先将该位置及其之后的元素都向后移动一位,为新元素腾出位置。这个操作的时间复杂度为O(N),频繁移动元素可能会导致效率问题,特别是集合中元素数量较多时
- 在日常开发中,若非所需,我们应当尽量避免在大集合中调用第二个插入方法
ArrayList的remove方法
remove(int index) 按照下标删除
nteger.MAX_VALUE - 8
主要是考虑到不同的JVM,有的JVM会在加入一些数据头,当扩容后的容量大于MAX_ARRAY_SIZE,我们会去比较最小需要容量和MAX_ARRAY_SIZE做比较,如果比它大, 只能取Integer.MAX_VALUE,否则是Integer.MAX_VALUE -8。这个是从jdk1.7开始才有的
参考资料
https://www.cnblogs.com/lcj12121/p/11710065.html