【问题标题】:Is removing multiple elements from a set in the middle of a foreach safe? [duplicate]是否从 foreach 安全中间的集合中删除多个元素? [复制]
【发布时间】:2016-01-24 03:46:04
【问题描述】:

下面的代码安全吗?假设它是单线程的。

for(String s : set){
    set.remove(s);
    set.remove(randomElementFromSet());
}

我很确定这应该没问题,但我想仔细检查一下,我不会冒迭代已删除元素的风险。

如果可能的话,请提供参考,以便我下次查找。

【问题讨论】:

  • 不,不是。您可以使用故障安全迭代器。更多信息请参考link
  • 不,它可能会抛出 ConcurrentModificationException。使用最后一条评论中所述的迭代器。
  • 你为什么不测试一下?如文档所述,使用标准 HashSet 或 TreeSet,您将获得 ConcurrentModificationException。
  • 您是否创建了测试场景并执行了代码?那已经回答了你的问题。

标签: java foreach set


【解决方案1】:

你试过了吗?你会得到 ConcurrentModificationException。

在对集合进行迭代时从集合中移除元素的一种安全方法是显式使用迭代器:

for(Iterator<String> iter = set.iterator(); iter.hasNext();) {
    String s = iter.next();
    iter.remove();
}

【讨论】:

    【解决方案2】:

    您不应该使用 for-each 循环过滤集合,因为您可以获得ConcurrentModificationException

    要正确执行此操作,您可以使用IteratorremoveIf。这两段代码都打印[Foo]

    使用Iterator

    Set<String> set = new HashSet<String>(Arrays.asList("Foo", "Bar", "Baz"));
    for (Iterator<String> i = set.iterator(); i.hasNext();)
        if (i.next().contains("B"))
            i.remove();
    System.out.println(set);
    

    使用removeIf (Java 8) 的方法:

    Set<String> set = new HashSet<>(Arrays.asList("Foo", "Bar", "Baz"));
    set.removeIf(str -> str.contains("B"));
    System.out.println(set);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-07
      • 2011-02-06
      • 2017-01-12
      • 1970-01-01
      • 2010-10-29
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多