春風博客

          春天里,百花香...

          導航

          <2007年12月>
          2526272829301
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          統計

          公告

          MAIL: junglesong@gmail.com
          MSN: junglesong_5@hotmail.com

          Locations of visitors to this page

          常用鏈接

          留言簿(11)

          隨筆分類(224)

          隨筆檔案(126)

          個人軟件下載

          我的其它博客

          我的鄰居們

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          遍歷并批量刪除容器中元素出現ConcurrentModificationException原因及處置

          在以下四種遍歷過程中,前兩種會拋出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(
          "----部門" + name + "人員名單---");

                  
          for (Member member : memberSheet) {
                      System.out.println(member);
                  }
              }

              
          /**
               * 里面的四個清除過程請分別獨立執行
               *
               
          */
              
          public void removeYoungerFromMemberSheet() {    
                  
          // 遍歷一:這個處理會拋出java.util.ConcurrentModificationException
                  for (Member member : memberSheet) {
                      
          if (member.getAge() < 30) {
                          memberSheet.remove(member);
                      }
                  }
                  
                  
          // 遍歷二:這個處理也會拋出java.util.ConcurrentModificationException
                  for (Iterator it = memberSheet.iterator(); it.hasNext();) {
                      Member member 
          = (Member) it.next();

                      
          if (member.getAge() < 30) {
                          memberSheet.remove(member);
                      }
                  }
                  
                  
          // 遍歷三:這個處理調用Iterator 本身的方法 remove(),會正常執行
                  for (Iterator it = memberSheet.iterator(); it.hasNext();) {
                      Member member 
          = (Member) it.next();

                      
          if (member.getAge() < 30) {
                          it.remove();
                      }
                  }
                  
                  
          // 遍歷四:這個處理不依賴Iterator,也會正常執行
                  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("研發部門");
                  resarchDept.addMemer(
          new Member("張三"38));
                  resarchDept.addMemer(
          new Member("李四"24));
                  resarchDept.addMemer(
          new Member("王五"30));
                  resarchDept.addMemer(
          new Member("錢七"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(
          " 所屬部門="+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;
              }
          }

          為什么會發生這樣的結果呢?這是因為

          "當使用 fail-fast iterator 對 Collection 或 Map 進行迭代操作過程中嘗試直接修改 Collection / Map 的內容時,即使是在單線程下運行, java.util.ConcurrentModificationException 異常也將被拋出。
          Iterator 是工作在一個獨立的線程中,并且擁有一個 mutex 鎖。 Iterator 被創建之后會建立一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變,所以當索引指針往后移動的時候就找不到要迭代的對象,所以按照 fail-fast 原則 Iterator 會馬上拋出 java.util.ConcurrentModificationException 異常。
          所以 Iterator 在工作的時候是不允許被迭代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除對象, Iterator.remove() 方法會在刪除當前迭代對象的同時維護索引的一致性。
          "

          上述這段資料來自http://hi.baidu.com/xjenator/blog/item/23b235a89041d4b0ca130c16.html.

          java.util包中很多迭代器都是所謂的fail-fast迭代器.這些迭代器如果發現集合被修改,而且不是通過迭代器本身,那么拋出一個異常進行清除-ConcurrentModificationException-從而避免不安全行為的發生.

          因此,第三種采用it.remove();不會出現任何異常,而第四不依賴于Iterator而依賴于索引當然更不會出現異常.

          代碼下載:
          http://www.aygfsteel.com/Files/sitinspring/ConcurrentModificationTest20071203210937.rar

          posted on 2007-12-03 21:04 sitinspring 閱讀(1881) 評論(2)  編輯  收藏 所屬分類: Java基礎

          評論

          # re: 遍歷并批量刪除容器中元素出現ConcurrentModificationException原因及處置 2007-12-04 09:09 BeanSoft

          不錯!  回復  更多評論   

          # re: 遍歷并批量刪除容器中元素出現ConcurrentModificationException原因及處置 2008-03-01 08:51 leequn1984

          第四種遍歷方法雖然不會拋 ConcurrentModificationException異常,但運行結果不是所期望的.應該寫成
          for (int i = membeerSheet.size() - 1;i >= 0; i--) {
          Member member = memberSheet.get(i);

          if (member.getAge() < 30) {
          memberSheet.remove(member);
          }
          }
          我的郵件是leequn1984@126.com,歡迎交流.  回復  更多評論   

          sitinspring(http://www.aygfsteel.com)原創,轉載請注明出處.
          主站蜘蛛池模板: 高阳县| 宜丰县| 安阳县| 彝良县| 双桥区| 浮山县| 玉溪市| 东莞市| 眉山市| 榆社县| 舞钢市| 云霄县| 闽侯县| 土默特左旗| 眉山市| 柘城县| 开平市| 安溪县| 邢台市| 元朗区| 西林县| 南汇区| 新津县| 泗洪县| 石家庄市| 宽甸| 嘉善县| 云阳县| 句容市| 泸溪县| 孟村| 颍上县| 宜川县| 太原市| 南汇区| 郑州市| 云霄县| 曲阜市| 桑植县| 祁东县| 定远县|