﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-空谷幽人-随笔分类-Java</title><link>http://www.blogjava.net/wingwing/category/44164.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 16 Mar 2010 05:08:14 GMT</lastBuildDate><pubDate>Tue, 16 Mar 2010 05:08:14 GMT</pubDate><ttl>60</ttl><item><title>【转载】使用 Iterator 或for-each注意：java.util.ConcurrentModificationException</title><link>http://www.blogjava.net/wingwing/archive/2010/03/02/314300.html</link><dc:creator>Li Ya Qiang</dc:creator><author>Li Ya Qiang</author><pubDate>Tue, 02 Mar 2010 08:50:00 GMT</pubDate><guid>http://www.blogjava.net/wingwing/archive/2010/03/02/314300.html</guid><wfw:comment>http://www.blogjava.net/wingwing/comments/314300.html</wfw:comment><comments>http://www.blogjava.net/wingwing/archive/2010/03/02/314300.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wingwing/comments/commentRss/314300.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wingwing/services/trackbacks/314300.html</trackback:ping><description><![CDATA[来自http://www.blogjava.net/fingki/archive/2010/03/02/314268.html<br />
<br />
在使用Iterator处理Collection时，注意java.util.ConcurrentModificationException。<br />
1.如果你仅仅是对collection进行遍历查询，那么不必担心什么。<br />
2.但如果你在遍历过程中要对collection进行删除，那么你就要注意了。<br />
For example:<br />
private&nbsp;void&nbsp;testDel()&nbsp;{&nbsp;&nbsp;
<ol start="1">
    <li>&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt;&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList&lt;String&gt;();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;10;&nbsp;i++)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str&nbsp;=&nbsp;"td"&nbsp;+&nbsp;i;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(str);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(Iterator&nbsp;it&nbsp;=&nbsp;list.iterator();&nbsp;it.hasNext();)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str&nbsp;=&nbsp;(String)&nbsp;it.next();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(str.equals("td5"))&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;list.remove(str);&nbsp;&nbsp;// 删除方法一&nbsp; <br />
    </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it.remove();&nbsp;&nbsp;// 删除方法二&nbsp; <br />
    </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp; <br />
    </li>
</ol>
上面的代码运行没有问题，但如果你用&#8220;方法一&#8221;替代&#8220;方法二&#8221;，则会出现
java.util.ConcurrentModificationException。<br />
（用for-each遍历也会出个类似问题）<br />
具体原因是可以看一下<span style="color: rgb(0, 0, 0);">先看看List中的remove方法源码：<br />
</span>
<ol start="1">
    <li>public&nbsp;boolean&nbsp;remove(Object&nbsp;o)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(o&nbsp;==&nbsp;null)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;index&nbsp;=&nbsp;0;&nbsp;index&nbsp;&lt;&nbsp;size;&nbsp;index++)&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(elementData[index]&nbsp;==&nbsp;null)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fastRemove(index);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;index&nbsp;=&nbsp;0;&nbsp;index&nbsp;&lt;&nbsp;size;&nbsp;index++)&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(o.equals(elementData[index]))&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fastRemove(index);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;false;&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>private&nbsp;void&nbsp;fastRemove(int&nbsp;index)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;modCount++;&nbsp;//&nbsp;特别注意这里，这里只增加了modCount的值&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;numMoved&nbsp;=&nbsp;size&nbsp;-&nbsp;index&nbsp;-&nbsp;1;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(numMoved&nbsp;&gt;&nbsp;0)&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.arraycopy(elementData,&nbsp;index&nbsp;+&nbsp;1,&nbsp;elementData,&nbsp;index,&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numMoved);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;elementData[--size]&nbsp;=&nbsp;null;&nbsp;//&nbsp;Let&nbsp;gc&nbsp;do&nbsp;its&nbsp;work&nbsp;&nbsp;</li>
    <li>}&nbsp; <br />
    </li>
</ol>
接着看。删除后得到下一个元素的代码，it.next():&nbsp; it为AbstractList的内部类Iterator的一个实例。<br />
<ol start="1">
    <li>public&nbsp;E&nbsp;next()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;checkForComodification();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E&nbsp;next&nbsp;=&nbsp;get(cursor);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastRet&nbsp;=&nbsp;cursor++;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;next;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(IndexOutOfBoundsException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;checkForComodification();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;NoSuchElementException();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>final&nbsp;void&nbsp;checkForComodification()&nbsp;{&nbsp; //注意这个方法<br />
    </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(modCount&nbsp;!=&nbsp;expectedModCount)&nbsp; //检查这两个值是否相同</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ConcurrentModificationException();&nbsp;&nbsp;</li>
    <li>}&nbsp; <br />
    </li>
</ol>
最后看Iterator的remove()方法的源代码：<br />
<ol start="1">
    <li>public&nbsp;void&nbsp;remove()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(lastRet&nbsp;==&nbsp;-1)&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;IllegalStateException();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;checkForComodification();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AbstractList.this.remove(lastRet);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(lastRet&nbsp;&lt;&nbsp;cursor)&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cursor--;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastRet&nbsp;=&nbsp;-1;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expectedModCount&nbsp;=&nbsp;modCount;&nbsp;//&nbsp;设置expectedModCount&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(IndexOutOfBoundsException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ConcurrentModificationException();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>final&nbsp;void&nbsp;checkForComodification()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(modCount&nbsp;!=&nbsp;expectedModCount)&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ConcurrentModificationException();&nbsp;&nbsp;</li>
    <li>}&nbsp; <br />
    </li>
</ol>
这下就明白了，list的remove方法只修改了modCount值，而iterator的remove能同步modCount和
expectedModCount.<br />
<img src ="http://www.blogjava.net/wingwing/aggbug/314300.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wingwing/" target="_blank">Li Ya Qiang</a> 2010-03-02 16:50 <a href="http://www.blogjava.net/wingwing/archive/2010/03/02/314300.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>