英文:
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
也允许同时进行迭代和更新。但问题在于,在迭代时可能无法看到正在进行的添加或删除的效果。
关于迭代的并发属性,可以从ConcurrentHashMap
的javadoc中推断出来。
还有其他方法吗?
这取决于您的需求,但可能有办法避免这个问题。例如,您可以:
- 在迭代之前复制集合,或者
- 在迭代时将新元素添加到另一个新集合,并在迭代过程中将现有元素添加到新集合中。
然而,这些方法在没有并发瓶颈的情况下可能不起作用(例如1),或者在行为上存在差异(例如2)。
英文:
The ConcurrentHashMap
class can be used for this. For example:
Set<T> set = Collections.newSetFromMap(new ConcurrentHashMap<T, Boolean>());
<sup>(You can replace <T, Boolean>
with <>
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:
- copy the set before iterating it, OR
- 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<Integer> original = new HashSet<>();
HashSet<Integer> elementsToAdd = new HashSet<>();
elementsToAdd.add(element); //while iterating original
original.addAll(elementsToAdd); //Once done with iterating, just add all.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论