O HashSet é baseado no HashMap.
Se observarmos a HashSet<E>
implementação, tudo será gerenciado HashMap<E,Object>
.
<E>
é usado como uma chave de HashMap
.
E sabemos que isso HashMap
não é seguro para threads. É por isso que temos ConcurrentHashMap
em Java.
Com base nisso, estou confuso de que por que não temos um ConcurrentHashSet que deve ser baseado no ConcurrentHashMap
?
Falta mais alguma coisa? Eu preciso usar Set
em um ambiente multiencadeado.
Além disso, se eu quiser criar o meu próprio, ConcurrentHashSet
posso consegui-lo apenas substituindo o HashMap
para ConcurrentHashMap
e deixando o resto como está?
java
collections
concurrency
hashmap
hashset
Talha Ahmed Khan
fonte
fonte
ConcurrentSkipListSet
é construídoConcurrentSkipListMap
, o que implementaConcurrentNavigableMap
eConcurrentMap
.Respostas:
Não existe um tipo incorporado
ConcurrentHashSet
porque você sempre pode derivar um conjunto de um mapa. Como existem muitos tipos de mapas, você usa um método para produzir um conjunto a partir de um determinado mapa (ou classe de mapa).Antes do Java 8, você produz um conjunto de hash simultâneo apoiado por um mapa de hash simultâneo, usando
Collections.newSetFromMap(map)
No Java 8 (apontado por @Matt), você pode obter uma visualização simultânea de conjunto de hash via
ConcurrentHashMap.newKeySet()
. Isso é um pouco mais simples que o antigo,newSetFromMap
que exigia que você passasse um objeto de mapa vazio. Mas é específico paraConcurrentHashMap
.De qualquer forma, os designers de Java poderiam ter criado uma nova interface de conjunto toda vez que uma nova interface de mapa fosse criada, mas esse padrão seria impossível de aplicar quando terceiros criam seus próprios mapas. É melhor ter os métodos estáticos que derivam novos conjuntos; essa abordagem sempre funciona, mesmo quando você cria suas próprias implementações de mapas.
fonte
ConcurrentHashMap
, perderá os benefícios dos quais obteriaConcurrentHashMap
?newSetFromMap
A implementação de é encontrada a partir da linha 3841 em docjar.com/html/api/java/util/Collections.java.html . É apenas um wrapper ....Collections.newSetFromMap
cria umSetFromMap
. por exemplo, oSetFromMap.removeAll
método delega para oKeySetView.removeAll
, que herda deConcurrentHashMap$CollectionView.removeAll
. Este método é altamente ineficiente para remover elementos em massa. imagineremoveAll(Collections.emptySet())
atravessar todos os elementos noMap
sem fazer nada. Ter umConcurrentHashSet
que seja implementado corretamente será melhor na maioria dos casos.fonte
Com o Guava 15 você também pode simplesmente usar:
fonte
Como Ray Toal mencionou, é tão fácil quanto:
fonte
ConcurrentHashMap
.Parece que o Java fornece uma implementação simultânea do conjunto com seu ConcurrentSkipListSet . Um conjunto SkipList é apenas um tipo especial de implementação de conjunto. Ele ainda implementa as interfaces Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, SortedSet. Isso pode funcionar para você se você precisar apenas da interface Set.
fonte
ConcurrentSkipListSet
os elementos devem serComparable
ConcurrentSkipListSet
menos que você queiraSortedSet
. Uma operação usual como adicionar ou remover deve ser O (1) para aHashSet
, mas O (log (n)) para aSortedSet
.Como apontado por isso a melhor maneira de obter um HashSet simultaneidade capaz é por meio de
Collections.synchronizedSet()
Isso funcionou para mim e eu não vi ninguém realmente apontando para isso.
EDIT Isso é menos eficiente do que a solução atualmente aprovada, como Eugene aponta, uma vez que apenas envolve seu conjunto em um decorador sincronizado, enquanto um
ConcurrentHashMap
implementa a simultaneidade de baixo nível e pode fazer o seu conjunto da mesma maneira. Então, obrigado ao Sr. Stepanenkov por deixar isso claro.http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-
fonte
synchronizedSet
método apenas cria o decorador em baixoCollection
para agrupar métodos que poderiam ser seguros para threads pela sincronização de toda a coleção. MasConcurrentHashMap
é implementado usando algoritmos sem bloqueio e sincronizações de "baixo nível" sem bloqueios de toda a coleção. Portanto, os invólucros deCollections.synchronized
... são piores em ambientes com vários threads por motivos de desempenho.Você pode usar goiabas
Sets.newSetFromMap(map)
para obter uma. O Java 6 também possui esse método emjava.util.Collections
fonte
fonte
Por que não usar: CopyOnWriteArraySet de java.util.concurrent?
fonte