繁体   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