使用Iterator 或for-each注意:java.util.ConcurrentModificationException

使用Iterator 或for-each注意:java.util.ConcurrentModificationException

Posted on 2010-03-02 12:22 Fingki.li 阅读(1360) 评论(1) 编辑 收藏 所属分类: About development <!-- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"> <rdf:Description rdf:about="http://www.blogjava.net/fingki/archive/2010/03/02/314268.html" dc:identifier="http://www.blogjava.net/fingki/archive/2010/03/02/314268.html" dc:title="使用Iterator 或for-each注意:java.util.ConcurrentModificationException" trackback:ping="http://www.blogjava.net/fingki/services/trackbacks/314268.aspx" /> </rdf:RDF> -->
在使用Iterator处理Collection时,注意java.util.ConcurrentModificationException。
1.如果你仅仅是对collection进行遍历查询,那么不必担心什么。
2.但如果你在遍历过程中要对collection进行删除,那么你就要注意了。
For example:
privatevoidtestDel(){
  1. List<String>list=newArrayList<String>();
  2. for(inti=0;i<10;i++){
  3. Stringstr="td"+i;
  4. list.add(str);
  5. }
  6. for(Iteratorit=list.iterator();it.hasNext();){
  7. Stringstr=(String)it.next();
  8. if(str.equals("td5")){
  9. //list.remove(str);// 删除方法一
  10. it.remove();// 删除方法二
  11. }
  12. }
  13. }
上面的代码运行没有问题,但如果你用“方法一”替代“方法二”,则会出现java.util.ConcurrentModificationException。
(用for-each遍历也会出个类似问题)
具体原因是可以看一下 先看看List中的remove方法源码:
  1. publicbooleanremove(Objecto){
  2. if(o==null){
  3. for(intindex=0;index<size;index++)
  4. if(elementData[index]==null){
  5. fastRemove(index);
  6. returntrue;
  7. }
  8. }else{
  9. for(intindex=0;index<size;index++)
  10. if(o.equals(elementData[index])){
  11. fastRemove(index);
  12. returntrue;
  13. }
  14. }
  15. returnfalse;
  16. }
  17. privatevoidfastRemove(intindex){
  18. modCount++;//特别注意这里,这里只增加了modCount的值
  19. intnumMoved=size-index-1;
  20. if(numMoved>0)
  21. System.arraycopy(elementData,index+1,elementData,index,
  22. numMoved);
  23. elementData[--size]=null;//Letgcdoitswork
  24. }
接着看。删除后得到下一个元素的代码,it.next(): it为AbstractList的内部类Iterator的一个实例。
  1. publicEnext(){
  2. checkForComodification();
  3. try{
  4. Enext=get(cursor);
  5. lastRet=cursor++;
  6. returnnext;
  7. }catch(IndexOutOfBoundsExceptione){
  8. checkForComodification();
  9. thrownewNoSuchElementException();
  10. }
  11. }
  12. finalvoidcheckForComodification(){ //注意这个方法
  13. if(modCount!=expectedModCount) //检查这两个值是否相同
  14. thrownewConcurrentModificationException();
  15. }
最后看Iterator的remove()方法的源代码:
  1. publicvoidremove(){
  2. if(lastRet==-1)
  3. thrownewIllegalStateException();
  4. checkForComodification();
  5. try{
  6. AbstractList.this.remove(lastRet);
  7. if(lastRet<cursor)
  8. cursor--;
  9. lastRet=-1;
  10. expectedModCount=modCount;//设置expectedModCount
  11. }catch(IndexOutOfBoundsExceptione){
  12. thrownewConcurrentModificationException();
  13. }
  14. }
  15. finalvoidcheckForComodification(){
  16. if(modCount!=expectedModCount)
  17. thrownewConcurrentModificationException();
  18. }
这下就明白了,list的remove方法只修改了modCount值,而iterator的remove能同步modCount和expectedModCount.

你可能感兴趣的:(使用Iterator 或for-each注意:java.util.ConcurrentModificationException)