阿里Java开发手册剖析:
-
6.5【强制】ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException
-
6.8【强制】在subList场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException
-
6.9【强制】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组。
-
6.11【强制】使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法, 它的 add/remove
-
6.14【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式
-
6.16【推荐】集合泛型定义时,在 JDK7 及以上,使用 diamond 语法或全省略。 说明:菱形泛型,即 diamond,直接使用<>来指代前边已经指定的类型。
【强制】在subList场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。
demo:
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
arrayList.add(5);
arrayList.add(6);
arrayList.add(7);
List<Integer> list = arrayList.subList(1, 3);
for (Integer integer : list) {
System.out.println(" "+integer);
}
System.out.println(" modify arrayList");
arrayList.remove(0);
for (Integer integer : list) {
System.out.println(" "+integer);
}
}
日志输出如下:
ArrayList中有个protected transient int modCount = 0;
用来记录当前ArrayList被修改的次数。比如add(),remove()
等都会导致modeCount增加:
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
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
return oldValue;
}
ArrayList.subList()会生成一个SubList的对象,SubList中有个对应modCount
同步ArrayList中的modeCount:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
protected transient int modCount = 0;
...
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
...
private class SubList extends AbstractList<E> implements RandomAccess {
...
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
//here
this.modCount = ArrayList.this.modCount;
}
...
}
}
SubList对象每次再遍历时,会将自己的modeCount
与ArrayList的modeCount
进行对比,如果两个值不一样就会报异常:ConcurrentModificationException
public ListIterator<E> listIterator(final int index) {
checkForComodification();
...
}
...
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}