日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

java集合中的一個(gè)移除數(shù)據(jù)陷阱(遍歷集合自身并同時(shí)刪除被遍歷數(shù)據(jù))

 為什么圖書館13 2016-06-28

新浪微博:IT國(guó)子監(jiān)(記得關(guān)注噢) http://weibo.com/itguozijian


下面是網(wǎng)上的其他解釋,更能從本質(zhì)上解釋原因:
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ù)索引的一致性。


     在java常用的集合框架就是list ,set ,map 。

      list 可通過(guò)下標(biāo)進(jìn)行遍歷,set,map不能通過(guò)下表進(jìn)行遍歷,因此對(duì)于set ,map的數(shù)據(jù)遍歷時(shí),常常采用迭代器,不過(guò)在使用迭代器移除數(shù)據(jù)時(shí)存在陷阱。

      執(zhí)行如下代碼:

 

        Set set = new HashSet();

        set.add(1);

        set.add(2);

        set.add(3);

        Iterator i = set.iterator();

        while(i.hashNext()){

        Object o = i.next();

         set.remove(o);

}

執(zhí)行結(jié)果會(huì)出現(xiàn)以下異常:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
    at java.util.AbstractList$Itr.next(Unknown Source)

這個(gè)問(wèn)題在集合框架使用迭代器遍歷數(shù)據(jù)時(shí)存在,在java5新曾的foreach遍歷方式下也存在。在通過(guò)下表遍歷list的過(guò)程中不存在著個(gè)問(wèn)題。

如:

   List list = new ArrayList();

  list .add(1);

list.add(2);

list.add(3);

for(int i = 0 ; i < list.size();i++){

   list.remove(list.get(i));|| list.remove(i);

}

//

或者使用iterator的remove方法

代碼能夠正常執(zhí)行。

 

當(dāng)然這種情況也是容易解決,實(shí)現(xiàn)方式就是講遍歷與移除操作分離,即在遍歷的過(guò)程中,將需要移除的數(shù)據(jù)存放在另外一個(gè)集合當(dāng)中,遍歷結(jié)束之后,統(tǒng)一移除。

------------------------------------------------------------------------------------------------------

利用java迭代器Itetator遍歷并刪除HashMap中的元素問(wèn)題

問(wèn)題:
下面的代碼試圖利用
HashMap的Iterator對(duì)象遍歷該HashMap并刪除滿足條件的元素(比如超時(shí)的元素),但會(huì)拋出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);      
        }   
}
    原因應(yīng)該
hs.remove(str)后,it內(nèi)容沒(méi)變,并且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);      
        }   
 
    ...........
    這樣的時(shí)間復(fù)雜度明顯太大(兩層循環(huán)嵌套)
    解決方案二:
由于刪除元素時(shí),hs的iterator對(duì)象也重新排序,所以只要用hs的一個(gè)副本hsBack
Uackp的iterator去遍歷hs即可,這樣在刪除hs元素時(shí)iterator就不會(huì)重排了(因?yàn)閯h除的是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);       
        }   
.....................
    這樣雖然時(shí)間復(fù)雜度小了(只有一層循環(huán)),可是空間復(fù)雜度大了(多了一個(gè)hashmap的拷貝);
    查閱api文檔和相關(guān)資料后,原來(lái)iterator對(duì)象有一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.

于是有下面的改進(jìn):
解決方案三:
..............................
Iterator it=hs.keySet().iterator(); 
while(it.hasNext())
{
String str=(String)it.next(); 
System.out.println(hs); 
it.remove(); 

..............................

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多