【问题标题】:Concurrent modification of two Set<String> by retainAll通过 retainAll 并发修改两个 Set<String>
【发布时间】:2021-01-15 07:55:33
【问题描述】:

我需要一些如何在迭代期间通过 retainAll 修改集合

假设我有下一个代码:

set.forEach(it - > {
    set.retainAll(someMapWithSets.get(it))
});

我已经尝试过使用迭代器的方法:

for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
    String value = iterator.next();
    set.retainAll(someMapWithSets.get(value))
}

它没有工作。 ConcurrentModificationException 被抛出。

如何正确地做到这一点?

更新。

整个任务是下一个:

我已经设置了

{A,B,C}

我有一组地图,表明元素是否兼容:

A: B,C - (means A is compatible with B and C and etc) 
B: A,E,C
C: A,B

我需要包含所有可能的兼容元素组合的集合地图:

A,B,C

因此,作为解决方案的一部分,我认为我可以创建仅保留给定集合和所选元素的兼容元素的方法。

 public static Set<String> define(Set<String> elements, String rootElement) {
        Set<String> result = someMapWithElements.get(rootElement);
        result.retainAll(elements);
        result.add(rootElement);
        result.forEach(it -> result.retainAll(someMapWithElements.get(it)))
        return result;
    }

但显然我得到ConcurrentModificationException

【问题讨论】:

  • 在另一个函数正在处理它的同时修改一个集合是违约;你为什么要这样做?你能具体说明你是如何修改这个集合的吗?可能有更好的解决方案。
  • 您必须在迭代时使用Iterator 对集合进行任何操作,否则您将获得ConcurrentModificationException。基本上你不能使用retainAll()。考虑改用流。
  • 嗨@dominicm00!我已经用详细信息更新了我的问题。谢谢。

标签: java


【解决方案1】:

在迭代同一个对象时,您不能使用retainAll 方法更改集合。因此,您需要创建一个新集合(或其他集合)以用作迭代变量,例如:

new HashSet(set).forEach(it - > {
    set.retainAll(someMapWithSets.get(it))
});

HashSet 可以替换为TreeSet 或任何其他合适的集合对象。

如果确实需要在迭代时更改集合,则需要使用Iterator 中的remove 方法。

【讨论】:

  • “您不能在迭代同一个对象时更改集合”错误。 “迭代器允许调用者在迭代期间以定义明确的语义从底层集合中删除元素”Source
  • 好的,你不能用这种方式改变它。答案仍然是我认为有效的答案。在 Iterator 中使用 remove 方法并不是对原始问题的回答,因为这意味着需要手动重新实现 retainAll。
  • 我认为您正在重新实现 Java 流。
  • 或许以您的观点提供答案将是最好的帮助方式
猜你喜欢
  • 2019-06-30
  • 1970-01-01
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
  • 2017-04-05
  • 2020-01-15
  • 2016-04-03
  • 2018-03-09
相关资源
最近更新 更多