/** 删除指定位置的元素 */ public E remove(int index){ rangeCheck(index);
modCount++; // 返回被删除的元素值 E oldValue = elementData(index);
int numMoved = size - index - 1; if (numMoved > 0) // 将 index + 1 及之后的元素向前移动一位,覆盖被删除值 System.arraycopy(elementData, index+1, elementData, index, numMoved); // 将最后一个元素置空,并将 size 值减1 elementData[--size] = null; // clear to let GC do its work
return oldValue; }
E elementData(int index){ return (E) elementData[index]; }
/** 删除指定元素,若元素重复,则只删除下标最小的元素 */ publicbooleanremove(Object o){ if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); returntrue; } } else { // 遍历数组,查找要删除元素的位置 for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); returntrue; } } returnfalse; }
/** 快速删除,不做边界检查,也不返回删除的元素值 */ privatevoidfastRemove(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 }
The iterators returned by this class’s iterator() and listIterator(int) methods are fail-fast if the list is structurally modified at any time after the iterator is created, in any way except through the iterator’s own ListIterator remove() or ListIterator add(Object) methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
List<String> a = new ArrayList<String>(); a.add("1"); a.add("2"); for (String temp : a) { System.out.println(temp); if("1".equals(temp)){ a.remove(temp); } } }
privateclassItrimplementsIterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount;
publicbooleanhasNext(){ return cursor != size; }
@SuppressWarnings("unchecked") public E next(){ // 并发修改检测,检测不通过则抛出异常 checkForComodification(); int i = cursor; if (i >= size) thrownew NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) thrownew ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } finalvoidcheckForComodification(){ if (modCount != expectedModCount) thrownew ConcurrentModificationException(); } // 省略不相关的代码 }
我们一步一步执行一下上面的代码,第一次进入 while 循环时,一切正常,元素 1 也被删除了。但删除元素 1 后,就无法再进入 while 循环,此时 it.hasNext() 为 false。原因是删除元素 1 后,元素计数器 size = 1,而迭代器中的 cursor 也等于 1,从而导致 it.hasNext() 返回false。归根结底,上面的代码段没抛异常的原因是,循环提前结束,导致 next 方法没有机会抛异常。不信的话,大家可以把代码稍微修改一下,即可发现问题:
1 2 3 4 5 6 7 8 9 10 11 12
List<String> a = new ArrayList<>(); a.add("1"); a.add("2"); a.add("3"); Iterator<String> it = a.iterator(); while (it.hasNext()) { String temp = it.next(); System.out.println("temp: " + temp); if("1".equals(temp)){ a.remove(temp); } }