Почему нет ConcurrentHashSet против ConcurrentHashMap



HashSet основан на HashMap.



если мы посмотрим на HashSet<E> реализация, все управляется под HashMap<E,Object>.



<E> используется в качестве ключа HashMap.



и мы это знаем HashMap не является потокобезопасным. Вот почему у нас есть ConcurrentHashMap в Java.



исходя из этого, я смущен, что почему у нас нет ConcurrentHashSet, который должен быть основан на ConcurrentHashMap?



что-нибудь еще Я пропал? Мне нужно использовать Set в многопоточной среде.



кроме того, если я хочу создать свою собственную ConcurrentHashSet могу ли я достичь этого, просто заменив HashMap до ConcurrentHashMap а остальное оставить как есть?

760   9  

9 ответов:

там нет встроенного типа для ConcurrentHashSet потому что вы всегда можете вывести набор из карты. Поскольку существует много типов карт, вы используете метод для создания набора из данной карты (или класса карты).

до Java 8 вы создаете параллельный хэш-набор, поддерживаемый параллельной хэш-картой, используя Collections.newSetFromMap(map)

в Java 8 (указано @Matt), вы можете получить параллельный набор хэшей посмотреть через ConcurrentHashMap.newKeySet(). Это немного проще, чем старый newSetFromMap который требовал, чтобы вы передали пустой объект карты. Но это специфично для ConcurrentHashMap.

в любом случае, разработчики Java могли бы создавать новый интерфейс набора каждый раз, когда создавался новый интерфейс карты, но этот шаблон было бы невозможно применить, когда третьи стороны создают свои собственные карты. Лучше иметь статические методы, которые выводят новые наборы; этот подход всегда работает, даже когда вы создаете свои собственные реализации Карты.

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

С гуавы 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;
   }
}

Почему бы не использовать: CopyOnWriteArraySet из java.утиль.одновременно?

Comments

    Ничего не найдено.