java.util.ConcurrentModificationException 時的解決辦
在對一個map進行迭代遍歷並刪除一些符合條件的鍵值對的時候,容易出現
java.util.ConcurrentModificationException 這個異常。
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:787)
at java.util.HashMap$KeyIterator.next(HashMap.java:823)
解決辦法如下:
import java.util.*;
public class TestMap {
public TestMap() {
}
public static void main(String[] args) {
java.util.Map m = new java.util.HashMap();
m.put("aaa", "lizongbo ");
m.put("bbb", " lizongbo");
m.put("ccc", "lizongbo ");
m.put("ddd", " lizongbo");
m.put("eee", "lizongbo");
m.put("fff", "lizongbo");
m.put("ggg", "lizongbo");
m.put("adads", "lizongbo");
m.put("dffd", "lizongbo");
m.put("dcxv", "lizongbo");
m.put("lizongbo", "lizongbo");
m.put("ert", "lizongbo");
m.put("544", "lizongbo ");
Iterator iterator = m.keySet().iterator();
while (iterator.hasNext()) {
String sessionId = (String) iterator.next();
if ("ggg".equals(sessionId) || "lizongbo".equals(sessionId) ||
"544".equals(sessionId)) {
iterator.remove(); //這行程式碼是關鍵。
m.remove(sessionId);
}
}
System.out.println(m.get("ggg"));
System.out.println(m.get("lizongbo"));
System.out.println(m.get("544"));
}
原因: jdk5.0以上的for-each也是利用內部的iterator來遍歷集合的(跟以前的iterator一樣)獲得的Iterator是一個內部類產生的迭代器,這個迭代器在呼叫next方法時,會檢查列表是否被修改過,如果被修改過,就會丟擲ConcurrentModificationException異常。進一步說,當使用 fail-fast iterator 對 Collection 或 Map 進行迭代操作過程中嘗試直接修改 Collection / Map 的內容時,即使是在單執行緒下運xi,java.util.ConcurrentModificationException 異常也將被丟擲。Iterator 是工作在一個獨立的執行緒中,並且擁有一個 mutex 鎖。 Iterator 被建立之後會建立一個指向原來物件的單鏈索引表,當原來的物件數量發生變化時,這個索引表的內容不會同步改變,所以當索引指標往後移動的時候就找不到要迭代的物件,所以按照 fail-fast 原則 Iterator 會馬上丟擲 java.util.ConcurrentModificationException 異常。 所以 Iterator 在工作的時候是不允許被迭代的物件被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除物件,Iterator.remove() 方法會在刪除當前迭代物件的同時維護索引的一致性。
有意思的是如果你的 Collection / Map 物件實際只有一個元素的時候, ConcurrentModificationException 異常並不會被丟擲。這也就是為什麼在 javadoc 裡面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
解決方法:在Map或者Collection的時候,不要用它們的API直接修改集合的內容,如果要修改可以用Iterator的remove()方法
由於for-each的寫法,使我們無法獲得iterator物件,所以這種遍歷方式不能進行刪除操作。只好改成了比較土的方法實現了,如下:
for (Iterator it = desk.getPkers().iterator(); it.hasNext();) {
PKer pkerOnDesk =(PKer) it.next();
it.remove();
}
相關文章
- java.util.ConcurrentModificationException解決詳解JavaException
- npm 使用安裝超時的解決辦法NPM
- 建庫時EM報錯的解決辦法
- jive發貼時NullPointException解決辦法NullException
- MySql登入時閃退的快速解決辦法MySql
- 解決PythonWin執行時崩潰的辦法Python
- 電腦時間不準怎麼辦 電腦時間不對的解決辦法
- 【git】Git commit時提示錯誤時 解決辦法GitMIT
- emca刪除em時間過長的解決辦法
- unity player 顯示播放錯誤時的解決辦法Unity
- bilibili 看影片時 GPU 狂飆的解決辦法.GPU
- CATIA許可證時間錯誤的解決辦法
- ubuntu域名解析暫時失效解決辦法Ubuntu
- ubantu 16.04 PHP 時間差 8 小時解決辦法PHP
- Ubuntu 16.04 PHP 時間差 8 小時解決辦法UbuntuPHP
- Gradle Resolve dependecies 很長時間的解決辦法Gradle
- 真機除錯時遇到“Couldnotlaunch***processlaunchfailed:Security”的解決辦法除錯AI
- 丟失Oracle中資料檔案Ora時的解決辦法Oracle
- OpenStack 的NAT解決辦法
- 公寓噪音的解決辦法
- oracle 11g awr不自動生成的臨時解決辦法Oracle
- 用CMD執行時Java,出現亂碼的解決辦法Java
- 臨時表空間使用率過高的解決辦法
- MYSQL++ 資料庫連線超時的解決辦法LTMySql資料庫
- Windows連線遠端桌面時出現黑屏的解決辦法Windows
- eclipse啟動時記憶體溢位的解決辦法Eclipse記憶體溢位
- LiveSDK初始化/登入時失敗的解決辦法
- 連線sql server時,不能使用127.0.0.1的解決辦法SQLServer127.0.0.1
- SSH在呼叫Service時獲取為空-解決辦法
- laravel8 時區設定無效解決辦法Laravel
- 使用預設pypi源出現連線超時的解決辦法
- Mysql5.7錯誤日誌時間不對的解決辦法MySql
- 時區錯誤導致oracle的EM不能啟動解決辦法Oracle
- Oracle opatch apply 時提示oci.dll has active的解決辦法OracleAPP
- SVN被鎖的解決辦法
- ORA-28056的解決辦法
- job都停了的解決辦法
- java.util.ConcurrentModificationExceptionJavaException