有没有一种数据结构,它没有重复的元素,但在迭代过程中可以添加元素?

huangapple go评论66阅读模式
英文:

Is there any data structure that has no duplicates but can have elements added to it while being iterated over?

问题

我知道一个集合没有重复项,但问题是当我使用迭代器或for each循环对其进行迭代时,我无法向其添加元素。有其他的办法吗?谢谢。

英文:

I know a set has no duplicates but the issue is that I can't add elements to it while iterating over it using an iterator or for each loop. Is there any other way? Thank you.

答案1

得分: 1

ConcurrentHashMap类可用于此目的。例如:

Set<T> set = Collections.newSetFromMap(new ConcurrentHashMap<T, Boolean>());

(您可以用<>替换<T, Boolean>,让编译器推断类型。我以上面的方式编写仅供说明。)

Collections::newSetFromMap javadoc 中提到:

返回由指定映射支持的集合。生成的集合显示与支持映射相同的排序、并发性和性能特性。实质上,此工厂方法提供与任何Map实现相对应的Set实现。

由于ConcurrentHashMap允许同时进行迭代和更新,因此上述代码生成的Set也允许同时进行迭代和更新。但问题在于,在迭代时可能无法看到正在进行的添加或删除的效果。

关于迭代的并发属性,可以从ConcurrentHashMapjavadoc中推断出来。


还有其他方法吗?

这取决于您的需求,但可能有办法避免这个问题。例如,您可以:

  1. 在迭代之前复制集合,或者
  2. 在迭代时将新元素添加到另一个新集合,并在迭代过程中将现有元素添加到新集合中。

然而,这些方法在没有并发瓶颈的情况下可能不起作用(例如1),或者在行为上存在差异(例如2)。

英文:

The ConcurrentHashMap class can be used for this. For example:

Set&lt;T&gt; set = Collections.newSetFromMap(new ConcurrentHashMap&lt;T, Boolean&gt;());

<sup>(You can replace &lt;T, Boolean&gt; with &lt;&gt; and let the compiler infer the types. I wrote it as above for illustrative purposes.)</sup>

The Collections::newSetFromMap javadoc says:

> Returns a set backed by the specified map. The resulting set displays the same ordering, concurrency, and performance characteristics as the backing map. In essence, this factory method provides a Set implementation corresponding to any Map implementation.

Since ConcurrentHashMap allows simultaneous iteration and updates, so does the Set produced as above. The catch is that an iteration may not see the effect of additions or removals made while iterating.

The concurrency properties of iteration can be inferred from the javadoc for ConcurrentHashMap.


> Is there any other way.

It depends on your requirements, but there are potentially ways to avoid the problem. For example, you could:

  1. copy the set before iterating it, OR
  2. add the new element to another new set and add the existing elements to the new set to the new set after ... or while ... iterating.

However, these these are unlikely to work without a concurrency bottleneck (e.g. 1.) or a differences in behavior (e.g. 2.)

答案2

得分: 0

不确定以下方法是否可以解决您的问题,但您可以尝试一下:

    HashSet<Integer> original = new HashSet<>();
    HashSet<Integer> elementsToAdd = new HashSet<>();
    elementsToAdd.add(element); //在迭代原始集合时
    original.addAll(elementsToAdd); //迭代完成后,只需全部添加。
英文:

Not sure whether below approach fixes your problem but you can try it:

    HashSet&lt;Integer&gt; original = new HashSet&lt;&gt;();
    HashSet&lt;Integer&gt; elementsToAdd = new HashSet&lt;&gt;();
    elementsToAdd.add(element); //while iterating original
    original.addAll(elementsToAdd); //Once done with iterating, just add all.

huangapple
  • 本文由 发表于 2020年5月30日 11:28:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/62097419.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定