Java集合类随手记——ArrayList

一、关于remove

  • 如果是remove(int index) 会先调用
private void rangeCheck(int index) {
  if (index >= size) 
  throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

这里有我们熟悉的IndexOutOfBoundsException数组越界异常;

  • 如果是remove(Object o) 会转化成数组下标调用
private void fastRemove(int index) {
   modCount++;
   int numMoved = size - index - 1;
   if (numMoved > 0)
     System.arraycopy(elementData, index+1, elementData, index,numMoved);
     elementData[--size] = null; // clear to let GC do its work
 }

最终调用System.arraycopy,以移动后续数据覆盖之前数据的方式实现删除。

二、关于保存数据的实体

transient Object[] elementData;

之所以定义成transient是因为,elementData默认初始化长度是10(DEFAULT_CAPACITY),当实际长度不足容量时,比如2,则后8个没存实际数据的位置是不会被序列化的。

三、关于forEach遍历时

  • 实际上for( : ) 是先会调用内部类Itr的hasNext判断是否有下个元素,
    之后调用next()取值给for中的变量。
  • 这里要注意,在next时会调用
final void checkForComodification() {
  if (modCount != expectedModCount)
     throw new ConcurrentModificationException();
}

其中modCount每次对数组操作都会++,记录操作次数。
而在迭代器遍历的过程中,一旦发现这个对象的mcount和迭代器中存储的mcount不一样那就抛异常。
这就是为什么我们循环遍历中第二次调用remove等操作会异常的原因。
Fail-Fast 机制在ArrayList,LinkedList,HashMap中都会看到。

  • modCount是定义在父类AbstractList.java中
protected transient int modCount = 0;

而expectenModCount定义在私有内部类(迭代器的实现)Itr中

int expectedModCount = modCount;

你可能感兴趣的:(Java集合类随手记——ArrayList)