Pourquoi il n’y a pas de ConcurrentHashSet contre ConcurrentHashMap

HashSet est basé sur HashMap.

Si nous examinons l’ HashSet de HashSet , tout est géré sous HashMap .

est utilisé comme clé de HashMap .

Et nous soaps que HashMap n’est pas thread-safe. C’est pourquoi nous avons ConcurrentHashMap en Java.

Sur cette base, je ne comprends pas pourquoi nous n’avons pas de ConcurrentHashSet qui devrait être basé sur ConcurrentHashMap ?

Y a-t-il autre chose qui me manque? Je dois utiliser Set dans un environnement multi-thread.

De même, si je veux créer mon propre ConcurrentHashSet puis-je y parvenir en remplaçant simplement HashMap par ConcurrentHashMap et en laissant le rest tel quel?

    Il n’y a pas de type intégré pour ConcurrentHashSet car vous pouvez toujours dériver un ensemble à partir d’une carte. Comme il existe de nombreux types de cartes, vous utilisez une méthode pour produire un ensemble à partir d’une carte donnée (ou d’une classe de carte).

    Avant Java 8, vous produisez un ensemble de hachage simultané sauvegardé par une carte de hachage simultanée, en utilisant Collections.newSetFromMap(map)

    Dans Java 8 (signalé par @Matt), vous pouvez obtenir une vue d’ ensemble de hachage simultanée via ConcurrentHashMap.newKeySet() . C’est un peu plus simple que l’ancien newSetFromMap qui vous obligeait à passer un object map vide. Mais il est spécifique à ConcurrentHashMap .

    Quoi qu’il en soit, les concepteurs Java auraient pu créer une nouvelle interface de jeu chaque fois qu’une nouvelle interface de carte était créée, mais ce modèle serait impossible à appliquer lorsque des tiers créeraient leurs propres cartes. Il est préférable d’avoir les méthodes statiques qui dérivent de nouveaux ensembles; cette approche fonctionne toujours, même lorsque vous créez vos propres implémentations de cartes.

     Set mySet = Collections.newSetFromMap(new ConcurrentHashMap()); 

    Avec Guava 15, vous pouvez également utiliser simplement:

     Set s = Sets.newConcurrentHashSet(); 

    Comme Ray Toal l’a mentionné, c’est aussi simple que:

     Set myConcurrentSet = ConcurrentHashMap.newKeySet(); 

    Il semble que Java fournisse une implémentation Set simultanée avec son ConcurrentSkipListSet . Un ensemble SkipList est juste un type particulier d’implémentation d’ensemble. Il implémente toujours les interfaces Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, SortedSet. Cela peut fonctionner pour vous si vous avez seulement besoin de l’interface Set.

    Vous pouvez utiliser Sets.newSetFromMap(map) de goyave pour en obtenir un. Java 6 a également cette méthode dans java.util.Collections

    Comme indiqué par ceci, le meilleur moyen d’obtenir un HashSet à access simultané est au moyen de Collections.synchronizedSet()

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

    Cela a fonctionné pour moi et je n’ai vu personne le montrer.

    EDIT Ceci est moins efficace que la solution actuellement approuvée, comme le fait remarquer Eugene, car elle enveloppe simplement votre set dans un décorateur synchronisé, alors qu’une ConcurrentHashMap implémente en fait la ConcurrentHashMap bas niveau et peut sauvegarder votre Set tout aussi bien. Merci donc à M. Stepanenkov d’avoir clarifié la situation.

    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 extends AbstractSet implements Set{ private final ConcurrentMap theMap; private static final Object dummy = new Object(); public ConcurrentHashSet(){ theMap = new ConcurrentHashMap(); } @Override public int size() { return theMap.size(); } @Override public Iterator 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; } } 

    Pourquoi ne pas utiliser: CopyOnWriteArraySet à partir de java.util.concurrent?