为什么没有针对ConcurrentHashMap的ConcurrentHashSet
HashSet基于HashMap。
如果我们看一下HashSet<E>
实现,所有东西都在HashMap<E,Object>
之下进行pipe理。
<E>
被用作HashMap
的关键字。
而且我们知道HashMap
不是线程安全的。 这就是为什么我们有Java中的ConcurrentHashMap
。
基于此,我很困惑, 为什么我们没有一个ConcurrentHashSet应该基于ConcurrentHashMap
?
还有什么我失踪? 我需要在multithreading环境中使用Set
。
另外,如果我想创build我自己的ConcurrentHashSet
,我可以通过将HashMap
replace为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?