remove的核心处理 & add在扩容或其余进行数组移动操做( eg. addAll、add(index, obj)), 时都涉及数组元素的复制移动:System.arraycopy调用native方式。java
从 index+1 至 end 的元素前移数组
在初始化时若没指定容量则构建的是空数组,在第一次add时,扩容至DEFAULT_CAPACITY= 10. this
默认下的扩容策略是: 原容量/2 (newCapacity = oldCapacity + (oldCapacity >> 1))spa
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容策略,再与肯定的最少知足容量大小比较 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; 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); }
在扩容时,须要经过Arrays.copyOf来复制数组元素(实现也是System.arraycopy)3d
public static void main(String[] args) throws Exception { ArrayList<String> list = new ArrayList<String>(1); Field file = ArrayList.class.getDeclaredField("elementData"); file.setAccessible(true); Object[] object = (Object[]) file.get(list); System.out.println("初始size: " + list.size()); System.out.println("初始数组容量:" + object.length); list.add("1"); Object[] object1 = (Object[]) file.get(list); System.out.println("添加第1个元素后的size:" + list.size()); System.out.println("添加第1个元素后的数组容量:" + object1.length); }
初始化指定容量执行结果:
code
初始化不指定容量执行结果:
blog
Iterator.remove()
方法)对集合增删元素外,是不容许直接对集合进行增删操做。不然将会抛出 ConcurrentModificationException
异常。因此,因为集合的for-Each循环本质上使用的仍是Iterator来迭代,所以也要注意这个陷阱。在for循环中直接remove时抛出异常
排序
普通的for循环方式删除元素时是经过System.arraycopy调用native的方式进行数组边界内的复制, size一直会在变化,结果没法控制(没法清空数据或下标越界异常)。继承
而for-Each循环是经过扩展Iterable接口的iterator()方法返回在ArrayList内部对于Iterator接口的实现类Itr来进行处理。接口
类中一个重要元素expectedModCount,初始值等于modCount。
在next()执行阶段会调用checkForComodification() 来断定modCount与expectedModCount是否一致, 不然抛出异常。
而在Iterator.remove方法会从新设置expectedModCount值, 因此当调用Iterator.next等方法时checkForComodification不会报错。