简体   繁体   English

Hashmap.keySet(),foreach和remove

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

I know that it's typically a big no-no to remove from a list using java's "foreach" and that one should use iterator.remove(). 我知道使用java的“foreach”从列表中删除通常是一个很大的禁忌,并且应该使用iterator.remove()。 But is it safe to remove() if I'm looping over a HashMap's keySet()? 但是如果我循环遍历HashMap的keySet(),那么remove()是否安全? Like this: 像这样:

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

EDIT: 编辑:

I hadn't noticed that you weren't really adding to the map - you were just changing the value within the entry. 我没有注意到你没有真正添加到地图 - 你只是改变了条目中的值。 In this case, pstanton's (pre-edit 1 ) solution is nearly right, but you should call setValue on the entry returned by the iterator, rather than calling map.put . 在这种情况下,pstanton(编辑前1 )解决方案几乎是正确的,但是你应该在迭代器返回的条目上调用setValue ,而不是调用map.put (It's possible that map.put will work, but I don't believe it's guaranteed - whereas the docs state that entry.setValue will work.) 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);
    }
}

(It's a shame that entry doesn't have a remove method, otherwise you could still use the enhanced for loop syntax, making it somewhat less clunky.) (遗憾的是, entry没有remove方法,否则你仍然可以使用增强的for循环语法,使它稍微不那么笨重。)

Old answer 老答案

(I've left this here for the more general case where you just want to make arbitrary modifications.) (我在这里留下了更常见的情况,你只想进行任意修改。)

No - you should neither add to the map nor remove from it directly. 不 - 您既不应该添加到地图中,也不应该直接删除它。 The set returned by HashSet.keySet() is a view onto the keys, not a snapshot. HashSet.keySet()返回的HashSet.keySet()是键的视图,而不是快照。

You can remove via the iterator, although that requires that you use the iterator explicitly instead of via an enhanced for loop. 可以通过迭代器删除,但这需要您显式使用迭代器而不是通过增强的for循环。

One simple option is to create a new set from the original: 一个简单的选择是从原始创建一个新集:

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

At this point you're fine, because you're not making any changes to the set. 此时你没事,因为你没有对套装做任何改变。

EDIT: Yes, you can definitely remove elements via the key set iterator. 编辑:是的,你绝对可以通过键集迭代器删除元素。 From the docs for HashMap.keySet() : HashMap.keySet()的文档:

The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. 该集支持元素删除,它通过Iterator.remove,Set.remove,removeAll,retainAll和clear操作从地图中删除相应的映射。 It does not support the add or addAll operations. 它不支持add或addAll操作。

This is even specified within the Map interface itself. 这甚至在Map接口本身中指定。


1 I decided to edit my answer rather than just commenting on psanton's, as I figured the extra information I'd got for similar-but-distinct situations was sufficiently useful to merit this answer staying. 1我决定编辑我的答案,而不仅仅是评论psanton的答案,因为我认为我得到的类似但不同的情况的额外信息对于值得这个答案保持足够有用。

you should use the entry set: 你应该使用条目集:

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);
}

EDIT fixed code 编辑固定代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将HashMap.keySet()转换为CharSequence []? - Convert HashMap.keySet() to CharSequence[]? 使用HashMap.keySet作为脏副本 - Using HashMap.keySet as a dirty copy hashmap.keyset()会按照它们添加到hashmap的顺序返回键吗? - Will hashmap.keyset() return keys in the order they were added to the hashmap? HashMap.keySet()如何返回键的视图? - How can HashMap.keySet() return a view of keys? HashMap.KeySet()在Java 7中以不同顺序返回键Java 8 - HashMap.KeySet() returns keys in different order in Java 7 Java 8 HashMap.values()/ HashMap.keySet()何时按引用返回,何时按值返回? - When Does HashMap.values()/HashMap.keySet() Return By Reference And When Does It Return By Value? HashMap.values()和HashMap.keySet()如何返回值和键? - How do HashMap.values() and HashMap.keySet() return values and keys? 如何从Java Rest服务在引导表中显示Java Hashmap.keySet()? - How to display Java Hashmap.keySet() in a bootstrap table, from a java rest service? 是什么导致java.util.HashSet和HashMap.keySet()类的iterator()稍微不可预测的排序? - What causes the slightly unpredictable ordering of the iterator() for the java.util.HashSet and HashMap.keySet() classes? HashMap中的keySet字段为null - keySet field in HashMap is null
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM