HashSet basiert auf HashMap.
Wenn wir uns die HashSet<E>
Implementierung ansehen , wird alles unter verwaltet HashMap<E,Object>
.
<E>
wird als Schlüssel von verwendet HashMap
.
Und wir wissen, dass HashMap
das nicht threadsicher ist. Deshalb haben wir ConcurrentHashMap
in Java.
Aufgrund dessen bin ich verwirrt, warum wir kein ConcurrentHashSet haben, das auf dem basieren sollte ConcurrentHashMap
.
Fehlt mir noch etwas? Ich muss Set
in einer Multithread-Umgebung verwenden.
Wenn ich meine eigenen erstellen möchte, ConcurrentHashSet
kann ich dies erreichen, indem ich einfach das HashMap
to ersetze ConcurrentHashMap
und den Rest unverändert lasse?
java
collections
concurrency
hashmap
hashset
Talha Ahmed Khan
quelle
quelle
ConcurrentSkipListSet
baut darauf aufConcurrentSkipListMap
, wasConcurrentNavigableMap
und implementiertConcurrentMap
.Antworten:
Es gibt keinen eingebauten Typ für,
ConcurrentHashSet
da Sie einen Satz immer von einer Karte ableiten können . Da es viele Arten von Karten gibt, verwenden Sie eine Methode, um einen Satz aus einer bestimmten Karte (oder Kartenklasse) zu erstellen.Vor Java 8 erstellen Sie mithilfe von einen gleichzeitigen Hash-Satz, der von einer gleichzeitigen Hash-Map unterstützt wird
Collections.newSetFromMap(map)
In Java 8 (von @Matt hervorgehoben) können Sie eine gleichzeitige Hash-Set- Ansicht über erhalten
ConcurrentHashMap.newKeySet()
. Dies ist etwas einfacher als das alte, beinewSetFromMap
dem Sie ein leeres Kartenobjekt übergeben mussten. Aber es ist spezifisch fürConcurrentHashMap
.Wie auch immer, die Java-Designer hätten jedes Mal, wenn eine neue Kartenschnittstelle erstellt wurde, eine neue Set-Schnittstelle erstellen können, aber dieses Muster wäre unmöglich durchzusetzen, wenn Dritte ihre eigenen Karten erstellen. Es ist besser, die statischen Methoden zu haben, die neue Mengen ableiten. Dieser Ansatz funktioniert immer, auch wenn Sie Ihre eigenen Kartenimplementierungen erstellen.
quelle
ConcurrentHashMap
die Vorteile verlieren, die Sie erhalten , wenn Sie das Set auf diese Weise erstellenConcurrentHashMap
?newSetFromMap
Die Implementierung finden Sie ab Zeile 3841 in docjar.com/html/api/java/util/Collections.java.html . Es ist nur eine Verpackung ...Collections.newSetFromMap
erstellt eineSetFromMap
. zBSetFromMap.removeAll
delegiert die Methode an dieKeySetView.removeAll
, die von erbtConcurrentHashMap$CollectionView.removeAll
. Diese Methode ist beim Entfernen von Massenelementen äußerst ineffizient. Stellen Sie sich vor, SieremoveAll(Collections.emptySet())
durchqueren alle Elemente im,Map
ohne etwas zu tun. Mit ein ,ConcurrentHashSet
die corretly umgesetzt wird , wird in den meisten Fällen besser sein.quelle
Mit Guava 15 können Sie auch einfach verwenden:
quelle
Wie Ray Toal erwähnt hat, ist es so einfach wie:
quelle
ConcurrentHashMap
.Es sieht so aus, als würde Java mit seinem ConcurrentSkipListSet eine gleichzeitige Set-Implementierung bereitstellen . Ein SkipList-Set ist nur eine spezielle Art der Set-Implementierung. Es implementiert weiterhin die Schnittstellen Serializable, Cloneable, Iterable, Collection, NavigableSet, Set und SortedSet. Dies funktioniert möglicherweise für Sie, wenn Sie nur die Set-Schnittstelle benötigen.
quelle
ConcurrentSkipListSet
die Elemente sein solltenComparable
ConcurrentSkipListSet
Sie es nur, wenn Sie eine möchtenSortedSet
. Eine übliche Operation wie Hinzufügen oder Entfernen sollte O (1) für a seinHashSet
, aber O (log (n)) für aSortedSet
.Wie hier gezeigt, ist der beste Weg, um ein paralleles HashSet zu erhalten, der über
Collections.synchronizedSet()
Das hat bei mir funktioniert und ich habe niemanden gesehen, der wirklich darauf hingewiesen hat.
BEARBEITEN Dies ist weniger effizient als die derzeit empfohlene Lösung, wie Eugene betont, da es Ihr Set nur in einen synchronisierten Dekorator einwickelt, während ein
ConcurrentHashMap
Set tatsächlich eine Parallelität auf niedriger Ebene implementiert und Ihr Set genauso gut unterstützen kann. Vielen Dank an Herrn Stepanenkov, der das klargestellt hat.http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-
quelle
synchronizedSet
Methode erstellt lediglich den Dekorator unterCollection
, um Methoden zu verpacken, die durch Synchronisieren der gesamten Sammlung threadsicher sein können. WirdConcurrentHashMap
jedoch unter Verwendung nicht blockierender Algorithmen und "Low-Level" -Synchronisationen ohne Sperren der gesamten Sammlung implementiert . Wrapper vonCollections.synchronized
... sind in Multi-Thread-Umgebungen aus Leistungsgründen schlechter.Sie können Guaven verwenden
Sets.newSetFromMap(map)
, um eine zu bekommen. Java 6 hat diese Methode auch injava.util.Collections
quelle
quelle
Warum nicht: CopyOnWriteArraySet aus java.util.concurrent verwenden?
quelle