問題:
下面的代碼試圖利用HashMap的Iterator對象遍歷該HashMap并刪除滿足條件的元素(比如超時的元素),但會拋出java.util.ConcurrentModificationException異常 public static void main(String[] args)
{
HashMap<String, String> hs=new HashMap();
hs.put("p1", "1");
hs.put("p2", "1");
hs.put("p3", "1");
hs.put("p4", "1");
hs.put("p5", "1");
hs.put("p6", "1");
Iterator it=hs.keySet().iterator();
while(it.hasNext())
{
String str=(String)it.next();
System.out.println(hs);
//邏輯處理.........
.............
hs.remove(str);
}
}
原因應該是hs.remove(str)后,it內容沒變,并且it里的指針列表又重新排序,所以只要確保刪除任一元素后,it保持同步更新即可:
解決方案一:刪除任一元素后,it保持同步更新
............
Iterator it=hs.keySet().iterator(); while(it.hasNext())
{
it=hs.keySet().iterator();
String str=(String)it.next();
System.out.println(hs);
//邏輯處理.........
.............
hs.remove(str);
}
...........
這樣的時間復雜度明顯太大(兩層循環嵌套)
解決方案二:
由于刪除元素時,hs的iterator對象也重新排序,所以只要用hs的一個副本hsBack
Uackp的iterator去遍歷hs即可,這樣在刪除hs元素時iterator就不會重排了(因為刪除的是hs的元素,而不是該iterator所屬的hsBackUackp)
...................
hsBackUp=(HashMap<String, String>)hs.clone();
Iterator it=hsBackUp.keySet().iterator();
System.out.println(hsBackUp);
while(it.hasNext())
{
String str=(String)it.next();
System.out.println(hs);
hs.remove(str);
}
.....................
這樣雖然時間復雜度小了(只有一層循環),可是空間復雜度大了(多了一個hashmap的拷貝);
查閱api文檔和相關資料后,原來iterator對象有一remove方法: void remove()
Removes from the underlying collection the last element returned by the
iterator (optional operation). This method can be called only once per
call to next. The behavior of an iterator is unspecified if
the underlying collection is modified while the iteration is in
progress in any way other than by calling this method.
于是有下面的改進:
解決方案三:
..............................
Iterator it=hs.keySet().iterator();
while(it.hasNext())
{
String str=(String)it.next();
System.out.println(hs);
it.remove();
}
..............................