簡體   English   中英

Hashmap.keySet(),foreach和remove

[英]Hashmap.keySet(), foreach, and remove

我知道使用java的“foreach”從列表中刪除通常是一個很大的禁忌,並且應該使用iterator.remove()。 但是如果我循環遍歷HashMap的keySet(),那么remove()是否安全? 像這樣:

for(String key : map.keySet()) {
  Node n = map.get(key).optimize();
  if(n == null) {
   map.remove(key);
  } else {
   map.put(key, n);
  }
}

編輯:

我沒有注意到你沒有真正添加到地圖 - 你只是改變了條目中的值。 在這種情況下,pstanton(編輯前1 )解決方案幾乎是正確的,但是你應該在迭代器返回的條目上調用setValue ,而不是調用map.put map.put 可能會起作用,但我不相信它是有保證的 - 而文檔聲明entry.setValue 起作用。)

for (Iterator<Map.Entry<String, Node>> it = map.entrySet().iterator(); 
     it.hasNext();)
{
    Map.Entry<String, Node> entry = it.next();
    Node n = entry.getValue().optimize();
    if(n == null) 
    {
        it.remove();
    }
    else
    {
        entry.setValue(n);
    }
}

(遺憾的是, entry沒有remove方法,否則你仍然可以使用增強的for循環語法,使它稍微不那么笨重。)

老答案

(我在這里留下了更常見的情況,你只想進行任意修改。)

不 - 您既不應該添加到地圖中,也不應該直接刪除它。 HashSet.keySet()返回的HashSet.keySet()是鍵的視圖,而不是快照。

可以通過迭代器刪除,但這需要您顯式使用迭代器而不是通過增強的for循環。

一個簡單的選擇是從原始創建一個新集:

for (String key : new HashSet<String>(map.keySet())) {
    ...
}

此時你沒事,因為你沒有對套裝做任何改變。

編輯:是的,你絕對可以通過鍵集迭代器刪除元素。 HashMap.keySet()的文檔:

該集支持元素刪除,它通過Iterator.remove,Set.remove,removeAll,retainAll和clear操作從地圖中刪除相應的映射。 它不支持add或addAll操作。

這甚至在Map接口本身中指定。


1我決定編輯我的答案,而不僅僅是評論psanton的答案,因為我認為我得到的類似但不同的情況的額外信息對於值得這個答案保持足夠有用。

你應該使用條目集:

for(Iterator<Map.Entry<String, Node>> it = map.entrySet().iterator(); it.hasNext();)
{
      Map.Entry<String, Node> entry = it.next();
      Node n = entry.getValue().optimize();
      if(n == null) 
          it.remove();
      else
          entry.setValue(n);
}

編輯固定代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM