晚上看了下ArrayList fail-fast机制,测试了几个例子,碰到一些趣事记录下
例子1:
public class Test {
public static void main(String[] args){
List<String> list = new ArrayList();
list.add("1");
list.add("2");
for(String param:list){
if("2".equals(param)){
list.remove("2");
}
}
System.out.println(list);
}
}
大家都知道fail-fast机制,所以结果毫无悬念的报错
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.Test.main(Test.java:14)
例子2:
public class Test {
public static void main(String[] args){
List<String> list = new ArrayList();
list.add("1");
list.add("2");
for(String param:list){
if("1".equals(param)){
list.remove("1");
}
}
System.out.println(list);
}
}
但是结果是[2]例子3:
public class Test {
public static void main(String[] args){
List<String> list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
for(String param:list){
if("1".equals(param)){
list.remove("1");
}
}
System.out.println(list);
}
}
结果依然报错
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.Test.main(Test.java:15)
例子4:
public class Test {
public static void main(String[] args){
List<String> list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
for(String param:list){
if("3".equals(param)){
list.remove("3");
}
}
System.out.println(list);
}
}
结果是[1, 2, 4]
综上所述,查阅源代码发现每次操作之前都会 checkForComodification进行检查
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
删除成功后会调用fastRemoe方法,modCout修改次数增加,而且会调用System.arraycopy方法进行数组复制。当倒数第二个元素for循环remove完后,游标已经指向最后一个元素,这时候链表长度已经减1,故不再进行判断,for循环结束。
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
}