Почему нет ConcurrentHashSet против ConcurrentHashMap
HashSet основан на HashMap.
если мы посмотрим на HashSet<E> реализация, все управляется под HashMap<E,Object>.
<E> используется в качестве ключа HashMap.
и мы это знаем HashMap не является потокобезопасным. Вот почему у нас есть ConcurrentHashMap в Java.
исходя из этого, я смущен, что почему у нас нет ConcurrentHashSet, который должен быть основан на ConcurrentHashMap?
что-нибудь еще Я пропал? Мне нужно использовать Set в многопоточной среде.
кроме того, если я хочу создать свою собственную ConcurrentHashSet могу ли я достичь этого, просто заменив HashMap до ConcurrentHashMap а остальное оставить как есть?
9 ответов:
там нет встроенного типа для
ConcurrentHashSetпотому что вы всегда можете вывести набор из карты. Поскольку существует много типов карт, вы используете метод для создания набора из данной карты (или класса карты).до Java 8 вы создаете параллельный хэш-набор, поддерживаемый параллельной хэш-картой, используя
Collections.newSetFromMap(map)в Java 8 (указано @Matt), вы можете получить параллельный набор хэшей посмотреть через
ConcurrentHashMap.newKeySet(). Это немного проще, чем старыйnewSetFromMapкоторый требовал, чтобы вы передали пустой объект карты. Но это специфично дляConcurrentHashMap.в любом случае, разработчики Java могли бы создавать новый интерфейс набора каждый раз, когда создавался новый интерфейс карты, но этот шаблон было бы невозможно применить, когда третьи стороны создают свои собственные карты. Лучше иметь статические методы, которые выводят новые наборы; этот подход всегда работает, даже когда вы создаете свои собственные реализации Карты.
С гуавы 15 вы также можете просто использовать:
Set s = Sets.newConcurrentHashSet();
Как Рэй Тол указано как:
Set<String> myConcurrentSet = ConcurrentHashMap.newKeySet();
похоже, что Java обеспечивает параллельную реализацию набора с его ConcurrentSkipListSet. А SkipList Set - это просто особый вид реализации. Он по-прежнему реализует Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, sortedset интерфейсы. Это может работать для вас, если вам нужен только набор интерфейс.
вы можете использовать гуавы
Sets.newSetFromMap(map)чтобы получить один. Java 6 также имеет этот метод вjava.util.Collections
как отмечает этой лучший способ получить хэш-набор с параллелизмом - это с помощью
Collections.synchronizedSet()Set s = Collections.synchronizedSet(new HashSet(...));Это сработало для меня, и я не видел, чтобы кто-то действительно указывал на это.
EDIT это менее эффективно, чем в настоящее время aproved решение, как указывает Евгений, так как он просто обертывает ваш набор в синхронизированный декоратор, в то время как
ConcurrentHashMapфактически реализует низкоуровневый параллелизм, и он может поддерживать ваш набор так же хорошо. Так спасибо господину Степаненкову за разъяснение.http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-
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; } }
Comments