4318 Stimmen

Was sind die Unterschiede zwischen einer HashMap und einer Hashtable in Java?

Was sind die Unterschiede zwischen einer HashMap und eine Hashtable in Java?

Was ist effizienter für Nicht-Thread-Anwendungen?

45 Stimmen

HashTable ist in Java 1.7 veraltet und es wird empfohlen, die Implementierung von ConcurrentMap zu verwenden

9 Stimmen

@MissFiona Nein, ConcurrentMap es no notwendig, da in der Frage von "Nicht-Thread-Anwendungen" die Rede ist, was bedeutet, dass Threading/Concurrency kein Thema ist.

9 Stimmen

@BasilBourque, Ja, aber ich glaube, was MissFiona damit meinte, war so etwas wie " HashTable wurde traditionell nur wegen seines partiellen Threading-Schutzes gewählt. Aber das wurde durch ConcurrentHashMap Daher gilt sie im Allgemeinen als im Ruhestand befindlich. Es wird allgemein empfohlen, zwischen HashMap o ConcurrentHashMap ." Und ich halte das für eine vernünftige Bemerkung, wenn sie es denn so gemeint hat.

4233voto

Josh Brown Punkte 50820

Es gibt mehrere Unterschiede zwischen HashMap y Hashtable in Java:

  1. Hashtable es synchronisiert in der Erwägung, dass HashMap nicht ist. Das macht HashMap besser für Nicht-Thread-Anwendungen, da unsynchronisierte Objekte in der Regel besser funktionieren als synchronisierte.

  2. Hashtable erlaubt nicht null Schlüssel oder Werte. HashMap erlaubt eine null Taste und eine beliebige Anzahl von null Werte.

  3. Eine der Unterklassen von HashMap ist LinkedHashMap Wenn Sie also eine vorhersehbare Iterationsreihenfolge wünschen (die standardmäßig die Einfügereihenfolge ist), können Sie einfach die HashMap für eine LinkedHashMap . Dies wäre nicht so einfach, wenn Sie die Hashtable .

Da die Synchronisierung für Sie kein Problem darstellt, würde ich empfehlen HashMap . Wenn die Synchronisierung zu einem Problem wird, können Sie sich auch mit ConcurrentHashMap .

135 Stimmen

Wenn Sie eine HashMap thread-sicher machen wollen, verwenden Sie Collections.synchronizedMap() .

349 Stimmen

Ich möchte auch anmerken, dass der naive Ansatz zur Thread-Sicherheit in Hashtable ("Die Synchronisierung jeder Methode sollte alle Gleichzeitigkeitsprobleme beseitigen!") macht es sehr viel schlechter für Anwendungen mit Gewinde. Sie sind besser dran, wenn Sie eine externe Synchronisierung einer HashMap (und über die Konsequenzen nachzudenken), oder die Verwendung einer ConcurrentMap Implementierung (und die Nutzung ihrer erweiterten API für die Gleichzeitigkeit). Fazit: Der einzige Grund für die Verwendung von Hashtable ist, wenn ein altes API (von ca. 1996) dies erfordert.

8 Stimmen

HashMap gibt dem Programmierer die Flexibilität, threadSafe Code zu schreiben, wenn er ihn tatsächlich benötigt. Es kam selten vor, dass ich eine thread-sichere Sammlung wie ConcurrentHashMap oder HashTable benötigte. Was ich brauchte, war ein bestimmter Satz von Funktionen oder bestimmte Anweisungen in einem synchronisierten Block, die thread-sicher sein sollten.

798voto

serg10 Punkte 30302

Beachten Sie, dass viele der Antworten angeben, dass Hashtable synchronisiert ist. In der Praxis bringt Ihnen das sehr wenig. Die Synchronisierung der Accessor-/Mutator-Methoden verhindert, dass zwei Threads gleichzeitig etwas zur Karte hinzufügen oder daraus entfernen, aber in der realen Welt werden Sie oft zusätzliche Synchronisierung benötigen.

Eine sehr gebräuchliche Redewendung ist "erst prüfen, dann setzen" - d. h. nach einem Eintrag in der Map und fügen Sie es hinzu, wenn es noch nicht vorhanden ist. Dies ist in keiner Weise ein atomarer Vorgang, egal ob Sie Hashtable o HashMap .

Eine gleichwertig synchronisierte HashMap kann durch erhalten werden:

Collections.synchronizedMap(myMap);

Aber um diese Logik korrekt umzusetzen, brauchen Sie zusätzliche Synchronisation in der Form:

synchronized(myMap) {
    if (!myMap.containsKey("tomato"))
        myMap.put("tomato", "red");
}

Auch die Iteration über eine Hashtable Einträge (oder eine HashMap erhalten durch Collections.synchronizedMap ) ist nicht thread-sicher, es sei denn, Sie schützen auch die Map vor Veränderungen durch zusätzliche Synchronisation zu schützen.

Implementierungen des ConcurrentMap Schnittstelle (zum Beispiel ConcurrentHashMap ) lösen einen Teil dieser Probleme, indem sie Thread-sichere "Check-then-act"-Semantik wie zum Beispiel:

ConcurrentMap.putIfAbsent(key, value);

63 Stimmen

Beachten Sie auch, dass Iteratoren, die auf eine HashMap zeigen, ungültig werden, wenn diese geändert wird.

3 Stimmen

Gibt es also einen Unterschied zwischen synchronized(myMap) {...} und ConcurrentHashMap in Bezug auf Thread sicher?

0 Stimmen

Da ich einige Jahre inmitten eines JVM-Entwicklungsteams gearbeitet habe, kann ich sagen, dass die interne Synchronisierung von Hashtable zumindest nützlich ist, um den Finger auf den Code des Kunden zu legen, wenn er fragwürdigen nebenläufigen Code schreibt. Wir erhielten mehrere Beschwerden über Fehler innerhalb von HashMap (und damit "offensichtlich" einen JDK/JVM-Bug), wenn die Ursache eine gleichzeitige Änderung war.

431voto

aberrant80 Punkte 12269

Hashtable wird als Legacy-Code betrachtet. Es gibt nichts über Hashtable die man nicht mit HashMap oder Ableitungen von HashMap Für neuen Code sehe ich also keine Rechtfertigung dafür, wieder zu Hashtable .

111 Stimmen

Aus Hashtable javadoc (Hervorhebung hinzugefügt): "Ab der Java 2 Plattform v1.2 wurde diese Klasse umgerüstet, um die Map-Schnittstelle zu implementieren, zu einem Mitglied des Java Collections Framework ." Sie haben jedoch Recht, dass es sich um Legacy-Code handelt. Alle Vorteile der Synchronisierung können mit Collections.synchronizedMap(HashMap) effizienter genutzt werden. (Ähnlich wie Vector eine Legacy-Version von Collections.synchronizedList(ArrayList) ist).

17 Stimmen

@aberrant80: leider haben Sie keine Wahl zwischen den beiden und müssen Hashtable verwenden, wenn Sie für J2ME programmieren...

0 Stimmen

Zustimmen, dass "Hashtable ist als Legacy-Code". Sie sollten stattdessen ConcurentHashMap verwenden, wenn Sie Gleichzeitigkeit benötigen.

232voto

sravan Punkte 5155

Diese Frage wird häufig in Vorstellungsgesprächen gestellt, um zu prüfen, ob der Bewerber die korrekte Verwendung von Sammelklassen versteht und sich der verfügbaren Alternativlösungen bewusst ist.

  1. El HashMap Klasse entspricht in etwa der Hashtable mit dem Unterschied, dass es nicht synchronisiert ist und Nullen zulässt. ( HashMap erlaubt Nullwerte als Schlüssel und Wert, während Hashtable erlaubt nicht null s).
  2. HashMap garantiert nicht, dass die Reihenfolge auf der Karte im Laufe der Zeit konstant bleibt.
  3. HashMap nicht synchronisiert ist, während Hashtable synchronisiert ist.
  4. Iterator in der HashMap ist ausfallsicher, während der Enumerator für die Hashtable nicht ist und werfen ConcurrentModificationException wenn ein anderer Thread die Map strukturell verändert, indem er ein Element hinzufügt oder entfernt, außer Iterator eigene remove() Methode. Dies ist jedoch kein garantiertes Verhalten und wird von der JVM nach bestem Wissen und Gewissen durchgeführt.

Hinweis auf einige wichtige Begriffe:

  1. Synchronisiert bedeutet, dass nur ein Thread eine Hash-Tabelle zu einem bestimmten Zeitpunkt ändern kann. Grundsätzlich bedeutet dies, dass jeder Thread vor der Durchführung einer Aktualisierung an einer Hashtable müssen eine Sperre für das Objekt erwerben, während andere darauf warten, dass die Sperre freigegeben wird.
  2. Die Ausfallsicherheit ist im Zusammenhang mit Iteratoren von Bedeutung. Wenn ein Iterator für ein Sammelobjekt erstellt wurde und ein anderer Thread versucht, das Sammelobjekt "strukturell" zu ändern, wird eine Ausnahme für gleichzeitige Änderungen ausgelöst. Es ist jedoch möglich, dass andere Threads die set Methode, da sie die Sammlung nicht "strukturell" verändert. Wenn jedoch vor dem Aufruf der set wurde die Sammlung strukturell verändert, IllegalArgumentException geworfen werden.
  3. Strukturelle Änderung bedeutet das Löschen oder Einfügen von Elementen, die die Struktur der Karte tatsächlich verändern könnten.

HashMap kann synchronisiert werden durch

Map m = Collections.synchronizeMap(hashMap);

Map bietet Auflistungsansichten anstelle einer direkten Unterstützung für die Iteration über Aufzählungsobjekte. Auflistungsansichten erweitern die Ausdruckskraft der Schnittstelle erheblich, wie später in diesem Abschnitt erläutert wird. Mit Map können Sie über Schlüssel, Werte oder Schlüssel-Wert-Paare iterieren; Hashtable bietet die dritte Möglichkeit nicht an. Map bietet eine sichere Möglichkeit, Einträge mitten in der Iteration zu entfernen; Hashtable nicht. Schließlich behebt Map einen kleinen Mangel in der Hashtable Schnittstelle. Hashtable hat eine Methode namens contains, die true zurückgibt, wenn die Hashtable einen bestimmten Wert enthält. Angesichts des Namens würde man erwarten, dass diese Methode true zurückgibt, wenn der Hashtable einen bestimmten Schlüssel enthalten, da der Schlüssel der primäre Zugangsmechanismus für eine Hashtable . Die Map-Schnittstelle beseitigt diese Quelle der Verwirrung durch Umbenennung der Methode containsValue . Außerdem wird dadurch die Konsistenz der Schnittstelle verbessert. containsValue parallelen containsKey .

Die Kartenschnittstelle

68 Stimmen

1) Die Iteratoren der HashMap sind NICHT ausfallsicher. Sie sind ausfallsicher. Es besteht ein großer Bedeutungsunterschied zwischen diesen beiden Begriffen. 2) Es gibt keine set Operation an einer HashMap . 3) Die put(...) Operation wirft nicht IllegalArgumentException wenn es eine frühere Änderung gab. 4) Das ausfallsichere Verhalten von HashMap auch tritt auf, wenn Sie eine Zuordnung ändern. 5) Das ausfallsichere Verhalten es garantiert. (Was nicht garantiert ist, ist das Verhalten eines HashTable wenn Sie eine gleichzeitige Änderung vornehmen. Das tatsächliche Verhalten ist ... unvorhersehbar.)

31 Stimmen

6) Hashtable garantiert auch nicht, dass die Reihenfolge der Kartenelemente im Laufe der Zeit stabil bleibt. (Sie verwechseln vielleicht Hashtable mit LinkedHashMap .)

5 Stimmen

Macht sich noch jemand Sorgen darüber, dass Studenten heutzutage auf die irrige Idee kommen, dass "synchronisierte Versionen" der Sammlungen irgendwie bedeuten, dass man zusammengesetzte Operationen nicht mehr extern synchronisieren muss? Mein Lieblingsbeispiel dafür ist thing.set(thing.get() + 1); die Neulinge oft als völlig ungeschützt überraschen, vor allem wenn die get() y set() sind synchronisierte Methoden. Viele von ihnen erwarten Magie.

156voto

Apocalisp Punkte 34088

HashMap : Eine Implementierung des Map Schnittstelle, die Hash-Codes zum Indizieren eines Arrays verwendet. Hashtable : Hallo, 1998 hat angerufen. Sie wollen ihre Sammel-API zurück.

Aber im Ernst: Es ist besser, wenn Sie sich von folgenden Dingen fernhalten Hashtable insgesamt. Für Single-Thread-Anwendungen brauchen Sie den zusätzlichen Overhead der Synchronisierung nicht. Bei hochgradig nebenläufigen Anwendungen kann die paranoide Synchronisierung zum Aushungern, zu Deadlocks oder zu unnötigen Pausen bei der Garbage Collection führen. Wie Tim Howland schon sagte, können Sie ConcurrentHashMap stattdessen.

0 Stimmen

Das macht tatsächlich Sinn. ConcurrentHashMaps gibt Ihnen die Freiheit der Synchronisation und das Debuggen ist viel einfacher.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X