天天看点

【转载】ArrayList 中数据删除 & fail fast

在循环arrayllist时,经常会遇到remove操作,那么arraylist的remove的底层是怎么做的?

abstractlist中,有一个属性modcount,这个属性是跟踪list中数据被修改的次数,任何对list的add/remove操作,都将导致modcount++.

在abstractlist中还有一个内部类itr implements iterator,itr是一个list遍历的工具类,当然list.iterator()方法也是返回itr对象,在itr中有一个校验位属性expectedmodcount;对于一个itr对象,其初始时expectedmodcount=modcount.

iterator是list一个视图,其最终还是操作list的存储结构.在使用iterator遍历时,remove()操作,会导致modcount++(abstractlist.remove()),但是还有expectedmodcount=modcount,即在iterator中remove数据,会带来expectedmodcount与modcount值的同步.

在iterator遍历时,next(),remove()方法会校验expectedmodcount与modcount值是否一致,如果不一致,就意味着这list数据在iterator外部被修改,此时iterator遍历将会造成concurrentmodificationexception.

abstractllist不仅支持普通的iterator,还支持listiterator(arraylist,linkedlist均支持),listiterator增加了遍历时双向游标能力(previous,next),增加了add方法.add方法和remove方法一样也做了expectedmodcount和modcount一致性校验.

引申一下,如下四个对list数据删除的代码,有区别吗??

如下是4中循环方式:

1),2),3)是最普通的遍历方式,但是在遍历并有删除操作时,似乎它们执行的结果还有些差距,根据坐标删除,那么1)实事上只会有一半被删掉,1)中每删除一次,计算一次list.size(),但是当前i++,且前端删除会造成数组结构copy.

2)后端删除,不会造成copy,每次都是删除最后一个位置,直至结束

3)因为size没有重新计算,在删除一半数据后,抛出indexoutofboundsexception

4)/5)正常

提示:foreach方式最终是转换成了iterator的方式进行.(产生于编译过程中).

继续阅读