日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

fail-fast机制(遍历的同时删除List中的对象)

發布時間:2025/3/16 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 fail-fast机制(遍历的同时删除List中的对象) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
遍歷刪除List中的元素有很多種方法,當運用不當的時候就會產生問題。下面主要看看以下幾種遍歷刪除List中元素的形式:

1.通過增強的for循環刪除符合條件的多個元素

2.通過增強的for循環刪除符合條件的一個元素

3.通過普通的for刪除刪除符合條件的多個元素

4.通過Iterator進行遍歷刪除符合條件的多個元素

?

[java] view plaincopy
  • /**??
  • ?*?使用增強的for循環??
  • ?*?在循環過程中從List中刪除非基本數據類型以后,繼續循環List時會報ConcurrentModificationException??
  • ?*/????
  • public?void?listRemove()?{????
  • ????List<Student>?students?=?this.getStudents();????
  • ????for?(Student?stu?:?students)?{????
  • ????????if?(stu.getId()?==?2)?????
  • ????????????students.remove(stu);????
  • ????}????
  • }????
  • [java] view plaincopy
  • /**??
  • ?*?像這種使用增強的for循環對List進行遍歷刪除,但刪除之后馬上就跳出的也不會出現異常??
  • ?*/????
  • public?void?listRemoveBreak()?{????
  • ????List<Student>?students?=?this.getStudents();????
  • ????for?(Student?stu?:?students)?{????
  • ????????if?(stu.getId()?==?2)?{????
  • ????????????students.remove(stu);????
  • ????????????break;????
  • ????????}????
  • ????}????
  • }????
  • [java] view plaincopy
  • /**??
  • ?*?這種不使用增強的for循環的也可以正常刪除和遍歷,??
  • ?*?這里所謂的正常是指它不會報異常,但是刪除后得到的??
  • ?*?數據不一定是正確的,這主要是因為刪除元素后,被刪除元素后??
  • ?*?的元素索引發生了變化。假設被遍歷list中共有10個元素,當??
  • ?*?刪除了第3個元素后,第4個元素就變成了第3個元素了,第5個就變成??
  • ?*?了第4個了,但是程序下一步循環到的索引是第4個,??
  • ?*?這時候取到的就是原本的第5個元素了。??
  • ?*/????
  • public?void?listRemove2()?{????
  • ????List<Student>?students?=?this.getStudents();????
  • ????for?(int?i=0;?i<students.size();?i++)?{????
  • ????????if?(students.get(i).getId()%3?==?0)?{????
  • ????????????Student?student?=?students.get(i);????
  • ????????????students.remove(student);????
  • ????????}????
  • ????}????
  • }????

  • [java] view plaincopy
  • /**??
  • ?*?使用Iterator的方式可以順利刪除和遍歷??
  • ?*/????
  • public?void?iteratorRemove()?{????
  • ????List<Student>?students?=?this.getStudents();????
  • ????System.out.println(students);????
  • ????Iterator<Student>?stuIter?=?students.iterator();????
  • ????while?(stuIter.hasNext())?{????
  • ????????Student?student?=?stuIter.next();????
  • ????????if?(student.getId()?%?2?==?0)????
  • ????????????stuIter.remove();//這里要使用Iterator的remove方法移除當前對象,如果使用List的remove方法,則同樣會出現ConcurrentModificationException????
  • ????}????
  • ????System.out.println(students);????
  • }????
  • 那么看到以上的幾段代碼之后,我們來分析一下他的原因,分析原因之前我們先來認識一個詞fail-fast

    百度百科是這么說的:

    fail-fast 機制是java集合(Collection)中的一種錯誤機制。當多個線程對同一個集合的內容進行操作時,就可能會產生fail-fast事件。例如:當某一個線程A通過iterator去遍歷某集合的過程中,若該集合的內容被其他線程所改變了;那么線程A訪問集合時,就會拋出ConcurrentModificationException異常,產生fail-fast事件。 要了解fail-fast機制,我們首先要對ConcurrentModificationException 異常有所了解。當方法檢測到對象的并發修改,但不允許這種修改時就拋出該異常。同時需要注意的是,該異常不會始終指出對象已經由不同線程并發修改,如果單線程違反了規則,同樣也有可能會拋出改異常。 誠然,迭代器的快速失敗行為無法得到保證,它不能保證一定會出現該錯誤,但是快速失敗操作會盡最大努力拋出ConcurrentModificationException異常,所以因此,為提高此類操作的正確性而編寫一個依賴于此異常的程序是錯誤的做法,正確做法是:ConcurrentModificationException 應該僅用于檢測 bug。
    ?? 當使用 fail-fast iterator 對 Collection 或 Map進行迭代操作過程中嘗試直接修改 Collection / Map 的內容時,即使是在單線程下運行,java.util.ConcurrentModificationException 異常也將被拋出。

    Iterator是工作在一個獨立的線程中,并且擁有一個 mutex 鎖。 Iterator被創建之后會建立一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變,所以當索引指針往后移動的時候就找不到要迭代的對象,所以按照 fail-fast 原則 Iterator 會馬上拋出java.util.ConcurrentModificationException 異常。

    所以 Iterator 在工作的時候是不允許被迭代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除對象, Iterator.remove() 方法會在刪除當前迭代對象的同時維護索引的一致性。

    有意思的是如果你的 Collection / Map 對象實際只有一個元素的時候,ConcurrentModificationException 異常并不會被拋出。這也就是為什么在 javadoc 里面指出: itwould be wrong to write a program that depended on this exception forits correctness: ConcurrentModificationException should be used only todetect bugs.

    附:來自ibm developerworks上對java.util.concurrent包的說明片段:
    ?????java.util 包中的集合類都返回 fail-fast 迭代器,這意味著它們假設線程在集合內容中進行迭代時,集合不會更改它的內容。如果fail-fast 迭代器檢測到在迭代過程中進行了更改操作,那么它會拋出 ConcurrentModificationException,這是不可控異常。
    ????? 在迭代過程中不更改集合的要求通常會對許多并發應用程序造成不便。相反,比較好的是它允許并發修改并確保迭代器只要進行合理操作,就可以提供集合的一致視圖,如 java.util.concurrent 集合類中的迭代器所做的那樣。
    ????java.util.concurrent 集合返回的迭代器稱為弱一致的(weakly consistent)迭代器。對于這些類,如果元素自從迭代開始已經刪除,且尚未由 next()方法返回,那么它將不返回到調用者。如果元素自迭代開始已經添加,那么它可能返回調用者,也可能不返回。在一次迭代中,無論如何更改底層集合,元素不會被返回兩次。

    新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!

    總結

    以上是生活随笔為你收集整理的fail-fast机制(遍历的同时删除List中的对象)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。