为什么没有针对ConcurrentHashMap的ConcurrentHashSet

HashSet基于HashMap。

如果我们看一下HashSet<E>实现,所有东西都在HashMap<E,Object>之下进行pipe理。

<E>被用作HashMap的关键字。

而且我们知道HashMap不是线程安全的。 这就是为什么我们有Java中的ConcurrentHashMap

基于此,我很困惑, 为什么我们没有一个ConcurrentHashSet应该基于ConcurrentHashMap

还有什么我失踪? 我需要在multithreading环境中使用Set

另外,如果我想创build我自己的ConcurrentHashSet ,我可以通过将HashMapreplace为ConcurrentHashMap并将其余部分保持原样来实现它?

ConcurrentHashSet没有内置types,因为您始终可以从地图派生一个集合。 由于地图types很多,因此您可以使用一种方法从给定的地图(或地图类)生成一个集合。

在Java 8之前,您通过使用Collections.newSetFromMap(map)生成由并发散列映射支持的并发散列集,

在Java 8中(由@Matt指出),你可以通过ConcurrentHashMap.newKeySet()获得并发的散列集合视图 。 这比旧的newSetFromMap要求你传入一个空的地图对象要简单一些。 但它是特定于ConcurrentHashMap

无论如何,每当创build一个新的地图界面时,Javadevise者都可以创build一个新的设置界面,但是当第三方创build他们自己的地图时,这种模式将无法执行。 拥有导出新集合的静态方法会更好; 即使在创build自己的地图实现时,该方法也可以正常工作。

 Set<String> mySet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); 

番石榴 15,你也可以简单地使用:

 Set s = Sets.newConcurrentHashSet(); 

看起来Java提供了ConcurrentSkipListSet的并发Set实现。 SkipList集只是一种特殊的集合实现。 它仍然实现了Serializable,Cloneable,Iterable,Collection,NavigableSet,Set,SortedSet接口。 如果您只需要Set界面,这可能适用于您。

你可以使用番石榴的Sets.newSetFromMap(map)来得到一个。 Java 6在java.util.Collections也有该方法

正如所指出的那样,获得并发HashSet的最好方法是通过Collections.synchronizedSet()

 Set s = Collections.synchronizedSet(new HashSet(...)); 

这对我工作,我还没有看到任何人真的指向它。

编辑这个效率低于目前推荐的解决scheme,正如Eugene指出的那样,因为它只是将你的集合包装到一个同步的装饰器中,而ConcurrentHashMap实际上实现了低层次的并发性,并且它可以支持你的Set。 所以谢谢Stepanenkov先生明确表示。

http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-

就像Ray Toal所说的那样简单:

 Set<String> myConcurrentSet = ConcurrentHashMap.newKeySet(); 
 import java.util.AbstractSet; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class ConcurrentHashSet<E> extends AbstractSet<E> implements Set<E>{ private final ConcurrentMap<E, Object> theMap; private static final Object dummy = new Object(); public ConcurrentHashSet(){ theMap = new ConcurrentHashMap<E, Object>(); } @Override public int size() { return theMap.size(); } @Override public Iterator<E> iterator(){ return theMap.keySet().iterator(); } @Override public boolean isEmpty(){ return theMap.isEmpty(); } @Override public boolean add(final E o){ return theMap.put(o, ConcurrentHashSet.dummy) == null; } @Override public boolean contains(final Object o){ return theMap.containsKey(o); } @Override public void clear(){ theMap.clear(); } @Override public boolean remove(final Object o){ return theMap.remove(o) == ConcurrentHashSet.dummy; } public boolean addIfAbsent(final E o){ Object obj = theMap.putIfAbsent(o, ConcurrentHashSet.dummy); return obj == null; } } 

为什么不使用:java.util.concurrent的CopyOnWriteArraySet?