2011-03-04 91 views
1

下面的代碼是刪除Hashtable中元素的安全方法嗎?刪除迭代中的散列表元素

Enumeration keys = siCache.keys(); //siCache is Hashtable 

    while(keys.hasMoreElements()) 
    { 
     String k = (String) keys.nextElement(); 
     Object v = siCache.get(k); 

     if(condition) siCache.remove(k); 

    } 
+0

我不明白爲什麼元素會被轉換成String。 'HashTable.remove'需要鍵本身,而不是'toString'。如果你的條件需要'字符串'出於某種原因,那很好,但不要使用ity作爲'HashTable.remove'的示例。 – 2011-03-04 06:18:52

+0

似乎。有沒有什麼特別的原因,但這不安全? – rkg 2011-03-04 06:21:34

+1

@Jon_darkstar問:toString()與cast到String有什麼關係?答:沒有。 – EJP 2011-03-04 06:36:52

回答

2

枚舉鍵時從Hashtable中刪除元素有潛在風險。這裏的javadoc中這樣說:

「因此,在併發的修改,迭代器很快就會完全失敗,而不是在將來不確定的時間冒着任意的,不確定行爲的Enumeration返回。通過Hashtable的關鍵和元素方法不是快速失敗的。「

含義是明確的:如果你這樣做,任意的,非確定性的行爲是可能的。

解決方案:

  • 如果您正在使用J2SE,使用keySet()。或者更好的是,不要使用Hashtable
  • 如果您正在使用J2ME,請構建要刪除的密鑰列表,並稍後刪除它們......或者祈禱:-)。
-1

這是安全的。但是,是什麼讓你覺得它可能不?

使用以下代碼進行測試。

public static void main(String[] args) { 
     // TODO Auto-generated method stub 

     Hashtable siCache = new Hashtable(); 
     siCache.put("key", "value"); 
     siCache.put("key1", "value1"); 
     Enumeration keys = siCache.keys(); //siCache is Hashtable 

     while(keys.hasMoreElements()) 
     { 
      String k = (String) keys.nextElement(); 
      Object v = siCache.get(k); 

      if(true) siCache.remove(k); 

     } 
     System.out.println(siCache.size()); 
    } 

輸出:0

+1

不,這並不安全。 – EJP 2011-03-04 06:37:49

+0

而這個例子也沒有證明任何東西。 – 2011-03-04 07:03:28

5

使用條目集,鍵集,或將值設置的迭代,並調用Iterator.remove()

+1

不,還有另一種安全技術:使用密鑰集的迭代器及其remove()方法。 :) – rlibby 2011-03-04 06:53:35

+0

小心提供一個完整的例子?我是新來的Java。謝謝 – pierrotlefou 2011-03-04 07:35:56

+0

另一個安全技術:使用VALUE的迭代器及其remove()方法。 :) – Timmos 2013-05-06 15:04:19

1

有使用之間存在明顯的區別...

Enumeration keys = siCache.keys(); 

,並使用...

Iterator iterator = siCache.entrySet().iterator() 

選項1,當你刪除元素集合中迭代,而不會拋出ConcurrentModificationException,而選項2將會。

至於爲什麼......我相信當你在你的例子中創建鍵Enumeration時,它是表鍵集的文字副本,它不會與對錶本身的修改保持同步。

這可能是也可能不是你的問題。如果表可以同時使用,但您可能想切換到使用集合迭代器。