HashSet se basa en HashMap.
Si nos fijamos en la HashSet<E>
implementación, todo se gestiona bajo HashMap<E,Object>
.
<E>
se usa como clave de HashMap
.
Y sabemos que HashMap
no es seguro para subprocesos. Por eso tenemos ConcurrentHashMap
en Java.
En base a esto, estoy confundido porque no tenemos un ConcurrentHashSet que debería basarse en el ConcurrentHashMap
?
¿Hay algo más que me estoy perdiendo? Necesito usar Set
en un entorno multiproceso.
Además, si quiero crear el mío, ConcurrentHashSet
¿puedo lograrlo simplemente reemplazando el HashMap
to ConcurrentHashMap
y dejando el resto como está?
java
collections
concurrency
hashmap
hashset
Talha Ahmed Khan
fuente
fuente
ConcurrentSkipListSet
se basaConcurrentSkipListMap
, que implementaConcurrentNavigableMap
yConcurrentMap
.Respuestas:
No hay un tipo incorporado
ConcurrentHashSet
porque siempre puedes derivar un conjunto de un mapa. Como hay muchos tipos de mapas, utiliza un método para producir un conjunto a partir de un mapa determinado (o clase de mapa).Antes de Java 8, produce un conjunto de hash simultáneo respaldado por un mapa de hash simultáneo, mediante el uso de
Collections.newSetFromMap(map)
En Java 8 (señalado por @Matt), puede obtener una vista de conjunto de hash simultáneo a través de
ConcurrentHashMap.newKeySet()
. Esto es un poco más simple que el anteriornewSetFromMap
que requería que pasaras un objeto de mapa vacío. Pero es específico deConcurrentHashMap
.De todos modos, los diseñadores de Java podrían haber creado una nueva interfaz de conjunto cada vez que se creó una nueva interfaz de mapa, pero ese patrón sería imposible de aplicar cuando terceros creen sus propios mapas. Es mejor tener los métodos estáticos que derivan nuevos conjuntos; ese enfoque siempre funciona, incluso cuando crea sus propias implementaciones de mapas.
fuente
ConcurrentHashMap
, pierde los beneficios que obtendríaConcurrentHashMap
?newSetFromMap
La implementación se encuentra a partir de la línea 3841 en docjar.com/html/api/java/util/Collections.java.html . Es solo una envoltura ...Collections.newSetFromMap
crea aSetFromMap
. por ejemplo, elSetFromMap.removeAll
método delega aKeySetView.removeAll
, que hereda deConcurrentHashMap$CollectionView.removeAll
. Este método es altamente ineficiente en la eliminación de elementos a granel. imagineremoveAll(Collections.emptySet())
atraviesa todos los elementosMap
sin hacer nada. Tener unaConcurrentHashSet
implementación correcta será mejor en la mayoría de los casos.fuente
Con Guava 15 también puedes usar simplemente:
fuente
Como Ray Toal mencionó, es tan fácil como:
fuente
ConcurrentHashMap
.Parece que Java proporciona una implementación de conjunto concurrente con su ConcurrentSkipListSet . Un conjunto SkipList es solo un tipo especial de implementación de conjunto. Todavía implementa las interfaces Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, SortedSet. Esto podría funcionar para usted si solo necesita la interfaz Set.
fuente
ConcurrentSkipListSet
los elementos deben serComparable
ConcurrentSkipListSet
menos que quiera unSortedSet
. Una operación habitual como agregar o quitar debería ser O (1) para aHashSet
, pero O (log (n)) para aSortedSet
.Como se ha señalado por esta la mejor manera de obtener un HashSet concurrencia-poder es por medio de
Collections.synchronizedSet()
Esto funcionó para mí y no he visto a nadie realmente señalando.
EDITAR Esto es menos eficiente que la solución aprobada actualmente, como señala Eugene, ya que simplemente envuelve su conjunto en un decorador sincronizado, mientras que en
ConcurrentHashMap
realidad implementa una concurrencia de bajo nivel y puede respaldar su Conjunto igual de bien. Así que gracias al Sr. Stepanenkov por dejar eso claro.http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-
fuente
synchronizedSet
método que se acaba crea el decorador bajoCollection
a los métodos de envoltura que podrían ser thread-safe por sincronización de toda la colección. PeroConcurrentHashMap
se implementa utilizando algoritmos sin bloqueo y sincronizaciones de "bajo nivel" sin ningún bloqueo de toda la colección. Entonces, los wrapers deCollections.synchronized
... son peores en entornos de subprocesos múltiples por razones de rendimiento.Puedes usar guayabas
Sets.newSetFromMap(map)
para conseguir uno. Java 6 también tiene ese método enjava.util.Collections
fuente
fuente
¿Por qué no usar: CopyOnWriteArraySet de java.util.concurrent?
fuente