在以下四種遍歷過(guò)程中,前兩種會(huì)拋出ConcurrentModificationException,而后兩種方法是正確的.
Department類:
package com.sitinspring;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Department {
private String name;
private List<Member> memberSheet;
public Department(String name) {
this.name = name;
}
public void addMemer(Member member) {
if (memberSheet == null) {
memberSheet = new ArrayList<Member>();
}
memberSheet.add(member);
}
public void printMemberSheet() {
System.out.println("----部門(mén)" + name + "人員名單---");
for (Member member : memberSheet) {
System.out.println(member);
}
}
/**
* 里面的四個(gè)清除過(guò)程請(qǐng)分別獨(dú)立執(zhí)行
*
*/
public void removeYoungerFromMemberSheet() {
// 遍歷一:這個(gè)處理會(huì)拋出java.util.ConcurrentModificationException
for (Member member : memberSheet) {
if (member.getAge() < 30) {
memberSheet.remove(member);
}
}
// 遍歷二:這個(gè)處理也會(huì)拋出java.util.ConcurrentModificationException
for (Iterator it = memberSheet.iterator(); it.hasNext();) {
Member member = (Member) it.next();
if (member.getAge() < 30) {
memberSheet.remove(member);
}
}
// 遍歷三:這個(gè)處理調(diào)用Iterator 本身的方法 remove(),會(huì)正常執(zhí)行
for (Iterator it = memberSheet.iterator(); it.hasNext();) {
Member member = (Member) it.next();
if (member.getAge() < 30) {
it.remove();
}
}
// 遍歷四:這個(gè)處理不依賴Iterator,也會(huì)正常執(zhí)行
for (int i=0;i<memberSheet.size();i++) {
Member member = memberSheet.get(i);
if (member.getAge() < 30) {
memberSheet.remove(member);
}
}
}
public String toString() {
return name;
}
public String getName() {
return name;
}
public static void main(String[] args) {
Department resarchDept = new Department("研發(fā)部門(mén)");
resarchDept.addMemer(new Member("張三", 38));
resarchDept.addMemer(new Member("李四", 24));
resarchDept.addMemer(new Member("王五", 30));
resarchDept.addMemer(new Member("錢(qián)七", 22));
resarchDept.addMemer(new Member("孫八", 39));
resarchDept.addMemer(new Member("周九", 30));
resarchDept.removeYoungerFromMemberSheet();
resarchDept.printMemberSheet();
}
}
Member類:
package com.sitinspring;
public class Member{
private String name;
private int age;
private Department department;
public Member(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
StringBuffer sb=new StringBuffer();
sb.append("員工名="+name);
sb.append(" 年齡="+age);
if(department!=null){
sb.append(" 所屬部門(mén)="+department);
}
return sb.toString();
}
public void changeNewDepartment(Department newDepartment) {
department.removeMemer(name);
newDepartment.addMemer(this);
}
public String getName() {
return name;
}
public void setDepartment(Department department) {
this.department = department;
}
}
為什么會(huì)發(fā)生這樣的結(jié)果呢?這是因?yàn)?br>
"
當(dāng)使用 fail-fast iterator 對(duì) Collection 或 Map 進(jìn)行迭代操作過(guò)程中嘗試直接修改 Collection / Map 的內(nèi)容時(shí),即使是在單線程下運(yùn)行, java.util.ConcurrentModificationException 異常也將被拋出。
Iterator 是工作在一個(gè)獨(dú)立的線程中,并且擁有一個(gè) mutex 鎖。 Iterator 被創(chuàng)建之后會(huì)建立一個(gè)指向原來(lái)對(duì)象的單鏈索引表,當(dāng)原來(lái)的對(duì)象數(shù)量發(fā)生變化時(shí),這個(gè)索引表的內(nèi)容不會(huì)同步改變,所以當(dāng)索引指針往后移動(dòng)的時(shí)候就找不到要迭代的對(duì)象,所以按照 fail-fast 原則 Iterator 會(huì)馬上拋出 java.util.ConcurrentModificationException 異常。
所以 Iterator 在工作的時(shí)候是不允許被迭代的對(duì)象被改變的。但你可以使用 Iterator 本身的方法 remove() 來(lái)刪除對(duì)象, Iterator.remove() 方法會(huì)在刪除當(dāng)前迭代對(duì)象的同時(shí)維護(hù)索引的一致性。"
上述這段資料來(lái)自http://hi.baidu.com/xjenator/blog/item/23b235a89041d4b0ca130c16.html.
java.util包中很多迭代器都是所謂的fail-fast迭代器.這些迭代器如果發(fā)現(xiàn)集合被修改,而且不是通過(guò)迭代器本身,那么拋出一個(gè)異常進(jìn)行清除-
ConcurrentModificationException-從而避免不安全行為的發(fā)生.因此,第三種采用it.remove();不會(huì)出現(xiàn)任何異常,而第四不依賴于Iterator而依賴于索引當(dāng)然更不會(huì)出現(xiàn)異常.
代碼下載:
http://www.blogjava.net/Files/sitinspring/ConcurrentModificationTest20071203210937.rar