Unterschiede zwischen HashMap und Hashtable?

3750

Was sind die Unterschiede zwischen a HashMapund a Hashtablein Java?

Was ist für Anwendungen ohne Thread effizienter?

dmanxiii
quelle
17
HashTable ist in Java 1.7 veraltet und es wird empfohlen, die ConcurrentMap-Implementierung zu verwenden
MissFiona
@MissFiona Nein, ConcurrentMapist hier nicht erforderlich, da in der Frage "Anwendungen ohne Thread" angegeben ist, was bedeutet, dass Threading / Parallelität kein Problem darstellt.
Basil Bourque

Antworten:

3774

Es gibt verschiedene Unterschiede zwischen HashMapund Hashtablein Java:

  1. Hashtableist synchronisiert , während dies HashMapnicht der Fall ist. Dies ist HashMapbesser für Anwendungen ohne Thread, da nicht synchronisierte Objekte in der Regel eine bessere Leistung erzielen als synchronisierte.

  2. Hashtableerlaubt keine nullSchlüssel oder Werte. HashMaperlaubt einen nullSchlüssel und eine beliebige Anzahl von nullWerten.

  3. Einer von HashMap der Subklassen ist LinkedHashMap, so in dem Fall , dass Sie vorhersehbar Iterationsreihenfolge wollen würden (der Auftrag standardmäßig ist), können Sie die Swap leicht HashMapfür ein LinkedHashMap. Dies wäre nicht so einfach, wenn Sie verwenden würden 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 dies auch überprüfen ConcurrentHashMap.

Josh Brown
quelle
84
Wenn Sie eine HashMap threadsicher machen möchten, verwenden Sie Collections.synchronizedMap().
Rok Strniša
275
Ich würde auch kommentieren, dass der naive Ansatz zur Thread-Sicherheit in Hashtable("Das Synchronisieren jeder Methode sollte sich um alle Parallelitätsprobleme kümmern!") Es für Thread-Anwendungen sehr viel schlimmer macht . Sie sind besser dran, eine extern zu synchronisieren HashMap(und über die Konsequenzen nachzudenken) oder eine ConcurrentMapImplementierung zu verwenden (und ihre erweiterte API für die Parallelität zu nutzen). Fazit: Der einzige Grund für die Verwendung Hashtableist, wenn eine Legacy-API (ab ca. 1996) dies erfordert.
Erickson
8
HashMap bietet Programmierern die Flexibilität, threadSafe-Code zu schreiben, wenn sie ihn tatsächlich verwenden. Es kam selten vor, dass ich eine thread-sichere Sammlung wie ConcurrentHashMap oder HashTable benötigte. Was ich brauchte, waren bestimmte Funktionen oder bestimmte Anweisungen in einem synchronisierten Block, um threadsicher zu sein.
Gaurava Agarwal
2
Hashtable ist veraltet und wir verwenden HashMap für eine nicht threadsichere Umgebung. Wenn Sie Thread-Sicherheit benötigen, können Sie Collections.synchronizedMap () oder ConcurrentHashMap verwenden, das effizienter ist als die Hashtabelle.
Maneesh Kumar
1
Es ist veraltet, aber nicht veraltet und ich frage mich, warum das so ist. Ich vermute, dass das Entfernen dieser Klasse (und von Vector aus den gleichen Gründen) zu viel vorhandenen Code beschädigen würde und das Annotieren mit @Deprecated die Absicht implizieren würde, den Code zu entfernen, der anscheinend nicht vorhanden ist.
Jilles van Gurp
682

Beachten Sie, dass in vielen Antworten angegeben ist, dass Hashtable synchronisiert ist. In der Praxis kauft Ihnen das sehr wenig. Die Synchronisierung erfolgt über die Accessor / Mutator-Methoden. Es werden zwei Threads gestoppt, die gleichzeitig zur Karte hinzugefügt oder daraus entfernt werden. In der realen Welt ist jedoch häufig eine zusätzliche Synchronisierung erforderlich.

Eine sehr gebräuchliche Redewendung ist "check then put" - dh suchen Sie nach einem Eintrag in der Mapund fügen Sie ihn hinzu, falls er noch nicht vorhanden ist. Dies ist in keiner Weise eine atomare Operation, egal ob Sie Hashtableoder verwenden HashMap.

Eine äquivalent synchronisierte HashMapkann erhalten werden durch:

Collections.synchronizedMap(myMap);

Um diese Logik korrekt zu implementieren, benötigen Sie jedoch eine zusätzliche Synchronisierung des Formulars:

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

Selbst das Iterieren über Hashtabledie Einträge eines (oder eines HashMapvon Collections.synchronizedMap) ist nicht threadsicher, es sei denn, Sie verhindern auch, dass das Mapdurch zusätzliche Synchronisierung geändert wird.

Implementierungen der ConcurrentMapSchnittstelle (zum Beispiel ConcurrentHashMap) lösen einige dieser Probleme, indem sie eine thread-sichere Check-Then-Act-Semantik enthalten, wie z.

ConcurrentMap.putIfAbsent(key, value);
serg10
quelle
53
Beachten Sie auch, dass Iteratoren, die darauf verweisen, ungültig werden, wenn eine HashMap geändert wird.
Chris K
3
Gibt es also einen Unterschied zwischen synchronisierter (myMap) {...} und ConcurrentHashMap in Bezug auf die Thread-Sicherheit?
Telebog
3
Sehr wahr, ich habe versucht, das gleiche hier zu erklären .. lovehasija.com/2012/08/16/…
Liebe Hasija
@ Bhushan: Es wird auf Best-Effort-Basis geworfen, dies ist kein garantiertes Verhalten: docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
Matt Stephenson
Nachdem ich einige Jahre in der Mitte einer JVM-Entwicklungsteams war, kann ich feststellen, dass die interne Synchronisation von Hashtable zumindest nützlich ist, um den Finger richtig auf den Code des Kunden zu richten, wenn er zwielichtigen gleichzeitigen Code schreibt. Wir haben mehrere Beschwerden über Fehler in HashMap erhalten (und damit "offensichtlich" einen JDK / JVM-Fehler), als die Ursache eine gleichzeitige Änderung war.
Hot Licks
363

Hashtablewird als Legacy-Code betrachtet. Es gibt nichts Hashtable, was nicht mit HashMapoder Ableitungen von getan werden kann HashMap, daher sehe ich für neuen Code keine Rechtfertigung für die Rückkehr zu Hashtable.

aberrant80
quelle
101
Aus Hashtable javadoc (Hervorhebung hinzugefügt): "Ab der Java 2-Plattform v1.2 wurde diese Klasse nachgerüstet, um die Map-Schnittstelle zu implementieren, sodass sie Mitglied des Java Collections Framework ist ." Sie haben jedoch Recht, dass es sich um Legacy-Code handelt. Alle Vorteile der Synchronisation können mit Collections.synchronizedMap (HashMap) effizienter erzielt werden. (Ähnlich wie Vector ist eine Legacy-Version von Collections.synchronizedList (ArrayList).)
Kip
15
@ aberrant80: Leider haben Sie keine Wahl zwischen den beiden und müssen Hashtable beim Programmieren für J2ME verwenden ...
pwes
6
Diese Antwort sollte gelöscht werden. Es enthält falsche Informationen und hat viele positive Stimmen.
anon58192932
@ anon58192932 Ist es möglich, die Frage zu bearbeiten, um sie zu beheben?
GC_
1
Wir müssen die Aufmerksamkeit des Posters @ aberrant80 oder eines Administrators durch Markieren auf sich ziehen. Das Markieren könnte helfen - werde das jetzt versuchen.
anon58192932
189

Diese Frage wird häufig im Interview gestellt, um zu überprüfen, ob der Kandidat die korrekte Verwendung von Sammlungsklassen versteht und sich der verfügbaren alternativen Lösungen bewusst ist.

  1. Die HashMapKlasse entspricht in etwa Hashtable, außer dass sie nicht synchronisiert ist und Nullen zulässt. ( HashMaperlaubt Nullwerte als Schlüssel und Wert, während s Hashtablenicht erlaubt ist null).
  2. HashMap garantiert nicht, dass die Reihenfolge der Karte über die Zeit konstant bleibt.
  3. HashMapist nicht synchronisiert, während Hashtablesynchronisiert ist.
  4. Der Iterator in the HashMapist ausfallsicher, während der Enumerator für Hashtableis nicht ist, und wird ausgelöst, ConcurrentModificationExceptionwenn ein anderer Thread die Map strukturell ändert, indem er ein Element außer Iteratorder eigenen remove() Methode hinzufügt oder entfernt . Dies ist jedoch kein garantiertes Verhalten und wird von JVM nach besten Kräften durchgeführt.

Hinweis zu einigen wichtigen Begriffen:

  1. Synchronisiert bedeutet, dass nur ein Thread eine Hash-Tabelle zu einem bestimmten Zeitpunkt ändern kann. Grundsätzlich bedeutet dies, dass jeder Thread, bevor er ein Update für a ausführt Hashtable, eine Sperre für das Objekt erhalten muss, während andere darauf warten, dass die Sperre aufgehoben wird.
  2. Ausfallsicher ist im Kontext von Iteratoren relevant. Wenn ein Iterator für ein Sammlungsobjekt erstellt wurde und ein anderer Thread versucht, das Sammlungsobjekt "strukturell" zu ändern, wird eine Ausnahme für gleichzeitige Änderungen ausgelöst. Es ist jedoch möglich, dass andere Threads die setMethode aufrufen , da die Sammlung nicht "strukturell" geändert wird. Wenn setdie Sammlung jedoch vor dem Aufruf strukturell geändert wurde, IllegalArgumentExceptionwird sie ausgelöst.
  3. Strukturelle Änderung bedeutet das Löschen oder Einfügen eines Elements, das die Struktur der Karte effektiv ändern könnte.

HashMap kann synchronisiert werden durch

Map m = Collections.synchronizeMap(hashMap);

Map bietet Sammlungsansichten anstelle der direkten Unterstützung für die Iteration über Aufzählungsobjekte. Sammlungsansichten verbessern die Ausdruckskraft der Benutzeroberfläche erheblich, wie später in diesem Abschnitt erläutert wird. Mit Map können Sie Schlüssel, Werte oder Schlüssel-Wert-Paare durchlaufen. Hashtablebietet nicht die dritte Option. Map bietet eine sichere Möglichkeit, Einträge während der Iteration zu entfernen. Hashtablenicht. Schließlich behebt Map einen kleinen Mangel in der HashtableBenutzeroberfläche. Hashtablehat eine Methode namens enthält, die true zurückgibt, wenn die Hashtableeinen bestimmten Wert enthält. Angesichts seines Namens würde man erwarten, dass diese Methode true zurückgibt, wenn Hashtablesie einen bestimmten Schlüssel enthält, da der Schlüssel der primäre Zugriffsmechanismus für a ist Hashtable. Die Map-Oberfläche beseitigt diese Verwirrung durch Umbenennen der Methode containsValue. Dies verbessert auch die Konsistenz der Schnittstelle - containsValueParallelen containsKey.

Die Kartenschnittstelle

sravan
quelle
19
Diese Antwort enthält mindestens 2 signifikante sachliche Ungenauigkeiten. Es verdient sicherlich nicht so viele positive Stimmen.
Stephen C
58
1) Die Iteratoren von HashMap sind NICHT ausfallsicher. Sie sind ausfallsicher. Es gibt einen großen Unterschied in der Bedeutung zwischen diesen beiden Begriffen. 2) Es gibt keine setOperation an a HashMap. 3) Die put(...)Operation wird nicht ausgelöst, IllegalArgumentExceptionwenn zuvor eine Änderung vorgenommen wurde. 4) Das Fail-Fast-Verhalten von tritt HashMap auch auf, wenn Sie eine Zuordnung ändern. 5) Das Fail-Fast-Verhalten ist garantiert. (Was nicht garantiert ist, ist das Verhalten von a, HashTablewenn Sie eine gleichzeitige Änderung vornehmen. Das tatsächliche Verhalten ist ... unvorhersehbar.)
Stephen C
25
6) Hashtablegarantiert nicht, dass die Reihenfolge der Kartenelemente auch über die Zeit stabil bleibt. (Sie verwechseln vielleicht Hashtablemit LinkedHashMap.)
Stephen C
4
Hat sich sonst noch jemand wirklich Sorgen gemacht, dass Studenten heutzutage die falsche Vorstellung haben, dass das Abrufen von "synchronisierten Versionen" der Sammlungen irgendwie bedeutet, dass Sie zusammengesetzte Operationen nicht extern synchronisieren müssen? Mein Lieblingsbeispiel dieses Wesens , thing.set(thing.get() + 1);das häufiger als nicht Neulinge überrascht als völlig ungeschützt fängt, vor allem , wenn die get()und set()Methoden synchronisiert werden . Viele von ihnen erwarten Magie.
Iteratoren auf HashMap sind nicht ausfallsicher
Abdul
130

HashMap: Eine Implementierung der MapSchnittstelle, die Hash-Codes verwendet, um ein Array zu indizieren. Hashtable: Hallo, 1998 angerufen. Sie möchten ihre Sammlungs-API zurück.

Im Ernst, du bist besser dran, dich von allem fernzuhalten Hashtable. Für Single-Threaded-Apps benötigen Sie keinen zusätzlichen Aufwand für die Synchronisierung. Bei Apps mit hoher Gleichzeitigkeit kann die paranoide Synchronisierung zu Hunger, Deadlocks oder unnötigen Pausen bei der Speicherbereinigung führen. Wie Tim Howland betonte, könnten Sie ConcurrentHashMapstattdessen verwenden.

Apocalisp
quelle
Das macht eigentlich Sinn. ConcurrentHashMaps bietet Ihnen die Freiheit der Synchronisation und das Debuggen ist viel einfacher.
Prap19
1
Ist dies spezifisch für Java oder die gesamte Implementierung der Hash-Map?
125

Beachten Sie, dass dies HashTableeine Legacy-Klasse war, bevor Java Collections Framework (JCF) eingeführt und später zur Implementierung der MapSchnittstelle nachgerüstet wurde . So war Vectorund Stack.

Halten Sie sich daher in neuem Code immer von ihnen fern, da es in der JCF immer eine bessere Alternative gibt, wie andere betont hatten.

Hier ist der Spickzettel der Java-Sammlung , den Sie nützlich finden. Beachten Sie, dass der graue Block die Legacy-Klassen HashTable, Vector und Stack enthält.

Geben Sie hier die Bildbeschreibung ein

pierrotlefou
quelle
72

Es gibt bereits viele gute Antworten. Ich füge einige neue Punkte hinzu und fasse sie zusammen.

HashMapund Hashtablebeide werden verwendet, um Daten in Schlüssel- und Wertform zu speichern . Beide verwenden die Hashing-Technik, um eindeutige Schlüssel zu speichern. Es gibt jedoch viele Unterschiede zwischen den unten angegebenen HashMap- und Hashtable-Klassen.

HashMap

  1. HashMapist nicht synchronisiert. Es ist nicht threadsicher und kann ohne richtigen Synchronisationscode nicht von vielen Threads gemeinsam genutzt werden.
  2. HashMap erlaubt einen Nullschlüssel und mehrere Nullwerte.
  3. HashMap ist eine neue Klasse, die in JDK 1.2 eingeführt wurde.
  4. HashMap ist schnell.
  5. Wir können das HashMapals synchronisieren, indem wir diesen Code aufrufen
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap wird von Iterator durchquert.
  7. Iterator in HashMapist ausfallsicher.
  8. HashMap erbt die AbstractMap-Klasse.

Hash-tabelle

  1. Hashtableist synchronisiert. Es ist threadsicher und kann mit vielen Threads geteilt werden.
  2. Hashtable erlaubt keinen Nullschlüssel oder Wert.
  3. Hashtable ist eine Legacy-Klasse.
  4. Hashtable ist langsam.
  5. Hashtable ist intern synchronisiert und kann nicht unsynchronisiert werden.
  6. Hashtable wird von Enumerator und Iterator durchlaufen.
  7. Enumerator in Hashtableist nicht ausfallsicher.
  8. Hashtable erbt die Dictionary-Klasse.

Lesen Sie weiter Was ist der Unterschied zwischen HashMap und Hashtable in Java?

Geben Sie hier die Bildbeschreibung ein

Roottraveller
quelle
Ziemlich genau in dieser Antwort behandelt (Duplikat von) - stackoverflow.com/a/39785829/432903 .
Prayagupd
Warum sagst du ~ " Hashtable ist eine Legacy-Klasse "? Wo ist die unterstützende Dokumentation dafür.
IgorGanapolsky
2
@IgorGanapolsky Sie können dies lesen - stackoverflow.com/questions/21086307/…
roottraveller
Die Wartung von HashMap ist teurer als die von TreeMap. Weil HashMap unnötige zusätzliche Buckets erstellt.
Abdul
64

Zusätzlich zu dem, was izb gesagt hat, sind HashMapNullwerte zulässig , während Hashtabledies nicht der Fall ist.

Beachten Sie auch, dass Hashtabledie DictionaryKlasse erweitert wird, die als Javadocs- Status veraltet ist und durch die MapSchnittstelle ersetzt wurde.

matt b
quelle
3
aber das macht die HashTable nicht obsolet, oder?
Pacerier
@Pacerier HashTable ist seit Java 1.7 veraltet.
Majid Ali Khan
62

Schauen Sie sich diese Tabelle an. Es bietet Vergleiche zwischen verschiedenen Datenstrukturen zusammen mit HashMapund Hashtable. Der Vergleich ist präzise, ​​klar und leicht verständlich.

Java-Sammlungsmatrix

Sujan
quelle
49

Hashtableist ähnlich wie HashMapund hat eine ähnliche Schnittstelle. Es wird empfohlen, dass Sie verwenden HashMap, es sei denn, Sie benötigen Unterstützung für ältere Anwendungen oder Sie benötigen eine Synchronisierung, da die HashtablesMethoden synchronisiert sind. In Ihrem Fall HashMapssind Sie also die beste Wahl, da Sie kein Multithreading betreiben .

Meilen D.
quelle
36

Ein weiterer wesentlicher Unterschied zwischen Hashtable und Hashmap besteht darin, dass der Iterator in der HashMap ausfallsicher ist, während der Enumerator für die Hashtable nicht ausfällt, und ConcurrentModificationException auslöst, wenn ein anderer Thread die Map strukturell ändert, indem er ein Element außer Iterators eigener remove () -Methode strukturell ändert oder entfernt. Dies ist jedoch kein garantiertes Verhalten und wird von JVM nach besten Kräften durchgeführt. "

Meine Quelle: http://javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html

Neerja
quelle
36

Neben all den anderen wichtigen Aspekten, die hier bereits erwähnt wurden, wird die Sammlungs-API (z. B. Kartenschnittstelle) ständig geändert, um den "neuesten und größten" Ergänzungen der Java-Spezifikation zu entsprechen.

Vergleichen Sie beispielsweise die Java 5 Map-Iteration:

for (Elem elem : map.keys()) {
  elem.doSth();
}

im Vergleich zum alten Hashtable-Ansatz:

for (Enumeration en = htable.keys(); en.hasMoreElements(); ) {
  Elem elem = (Elem) en.nextElement();
  elem.doSth();
}

In Java 1.8 wird uns auch versprochen, HashMaps wie in guten alten Skriptsprachen erstellen und darauf zugreifen zu können:

Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];

Update: Nein, sie werden nicht in 1.8 landen ... :(

Werden die Sammlungsverbesserungen von Project Coin in JDK8 enthalten sein?

pwes
quelle
34

Hashtableist synchronisiert, wohingegen HashMapnicht. Das macht Hashtablelangsamer als Hashmap.

Verwenden HashMapSie Apps ohne Thread, da sie ansonsten hinsichtlich der Funktionalität identisch sind.

izb
quelle
30
  • HashTable ist synchronisiert. Wenn Sie es in einem einzelnen Thread verwenden, können Sie HashMap verwenden , eine nicht synchronisierte Version. Nicht synchronisierte Objekte sind oft etwas leistungsfähiger. Übrigens, wenn mehrere Threads gleichzeitig auf eine HashMap zugreifen und mindestens einer der Threads die Map strukturell ändert, muss sie extern synchronisiert werden. Sie können eine nicht synchronisierte Karte in eine synchronisierte umschließen, indem Sie Folgendes verwenden:

    Map m = Collections.synchronizedMap(new HashMap(...));
  • HashTable kann nur Nicht-Null-Objekte als Schlüssel oder als Wert enthalten. HashMap kann einen Nullschlüssel und Nullwerte enthalten.

  • Die von Map zurückgegebenen Iteratoren sind ausfallsicher, wenn die Map zu irgendeinem Zeitpunkt nach dem Erstellen des Iterators strukturell geändert wird, außer durch die eigene Entfernungsmethode des Iterators ConcurrentModificationException. Der Iterator löst a aus . Daher fällt der Iterator angesichts gleichzeitiger Änderungen schnell und sauber aus, anstatt zu einem unbestimmten Zeitpunkt in der Zukunft willkürliches, nicht deterministisches Verhalten zu riskieren. Während die von den Schlüssel- und Elementmethoden von Hashtable zurückgegebenen Aufzählungen nicht ausfallsicher sind.

  • HashTable und HashMap sind Mitglied des Java Collections Framework (seit der Java 2-Plattform v1.2 wurde HashTable zur Implementierung der Map-Schnittstelle nachgerüstet).

  • HashTable wird als Legacy-Code betrachtet. In der Dokumentation wird empfohlen, ConcurrentHashMap anstelle von Hashtable zu verwenden, wenn eine thread-sichere, hochkonkurrierende Implementierung gewünscht wird.

  • HashMap garantiert nicht die Reihenfolge, in der Elemente zurückgegeben werden. Für HashTable ist es wahrscheinlich dasselbe, aber ich bin mir nicht ganz sicher, ich finde keine Ressource, die dies eindeutig angibt.

alain.janinm
quelle
30

HashMapund Hashtablehaben auch signifikante algorithmische Unterschiede. Niemand hat dies zuvor erwähnt, deshalb spreche ich es an. HashMaperstellt eine Hash-Tabelle mit einer Potenz von zwei Größen, erhöht sie dynamisch so, dass sich höchstens acht Elemente (Kollisionen) in einem Bucket befinden, und rührt die Elemente für allgemeine Elementtypen sehr gut um. Die HashtableImplementierung bietet jedoch eine bessere und feinere Kontrolle über das Hashing, wenn Sie wissen, was Sie tun. Sie können die Tabellengröße beispielsweise anhand der Primzahl festlegen, die Ihrer Wertedomänengröße am nächsten kommt. Dies führt zu einer besseren Leistung als HashMap, dh weniger Kollisionen für einige Fälle.

Abgesehen von den offensichtlichen Unterschieden, die in dieser Frage ausführlich erörtert werden, sehe ich den Hashtable als Auto mit "manuellem Antrieb", bei dem Sie eine bessere Kontrolle über das Hashing haben, und die HashMap als Gegenstück mit "automatischem Antrieb", das im Allgemeinen eine gute Leistung erbringt.

SkyWalker
quelle
27

Aufgrund der Informationen hier würde ich empfehlen, mit HashMap zu arbeiten. Ich denke, der größte Vorteil ist, dass Java Sie daran hindert, es zu ändern, während Sie darüber iterieren, es sei denn, Sie tun dies über den Iterator.

pkaeding
quelle
5
Es verhindert es nicht wirklich, es erkennt es nur und löst einen Fehler aus.
Bart van Heukelom
1
Ich bin mir ziemlich sicher, dass eine ConncurrentModificationException ausgelöst wird, bevor die zugrunde liegende Sammlung geändert wird, obwohl ich mich irren könnte.
pkaeding
Es wird versucht , gleichzeitige Änderungen zu erkennen und eine Ausnahme auszulösen. Aber wenn Sie etwas mit Threads machen, kann es keine Versprechungen machen. Es kann absolut alles passieren, auch Bruch .
CHao
24

A Collection- manchmal auch Container genannt - ist einfach ein Objekt, das mehrere Elemente zu einer Einheit zusammenfasst. Collections werden zum Speichern, Abrufen, Bearbeiten und Kommunizieren aggregierter Daten verwendet. Ein Sammlungsframework W ist eine einheitliche Architektur zum Darstellen und Bearbeiten von Sammlungen.

Die HashMap JDK1.2und die Hashtabelle JDK1.0werden beide verwendet, um eine Gruppe von Objekten darzustellen, die <Key, Value>paarweise dargestellt werden. Jedes <Key, Value>Paar heißt EntryObjekt. Die Sammlung von Einträgen wird durch den Gegenstand von HashMapund bezeichnet Hashtable. Schlüssel in einer Sammlung müssen eindeutig oder unverwechselbar sein. [da sie verwendet werden, um einen zugeordneten Wert eines bestimmten Schlüssels abzurufen. Werte in einer Sammlung können dupliziert werden.]


« Mitglied des Superclass, Legacy and Collection Framework

Hashtable ist eine in eingeführte Legacy-Klasse JDK1.0, die eine Unterklasse der Dictionary-Klasse ist. From JDK1.2Hashtable wurde überarbeitet, um die Map-Schnittstelle zu implementieren und Mitglied des Collection-Frameworks zu werden. HashMap ist seit Beginn seiner Einführung in Java Collection Framework Mitglied JDK1.2. HashMap ist die Unterklasse der AbstractMap-Klasse.

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable { ... }

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }

« Anfangskapazität und Lastfaktor

Die Kapazität ist die Anzahl der Buckets in der Hash-Tabelle, und die anfängliche Kapazität ist einfach die Kapazität zum Zeitpunkt der Erstellung der Hash-Tabelle. Beachten Sie, dass die Hash-Tabelle geöffnet ist: Im Fall eines " hashcollision" speichert ein einzelner Bucket mehrere Einträge, die nacheinander durchsucht werden müssen. Der Auslastungsfaktor ist ein Maß dafür, wie voll die Hash-Tabelle werden darf, bevor ihre Kapazität automatisch erhöht wird.

HashMap erstellt eine leere Hash-Tabelle mit der Standard-Anfangskapazität (16) und dem Standard-Ladefaktor (0,75). Wobei als Hashtable eine leere Hashtable mit einer Standard-Anfangskapazität (11) und einem Lastfaktor / Füll-Verhältnis (0,75) erstellt wird.

Hash Map & Hashtable

« Strukturänderung bei Hash-Kollision

HashMap, HashtableBei Hash - Kollisionen sie speichern die Map - Einträge in verknüpften Listen. Wenn in Java8 derHashMap Hash-Bucket einen bestimmten Schwellenwert überschreitet, wechselt dieser Bucket von linked list of entries to a balanced tree. die die Worst-Case-Leistung von O (n) auf O (log n) verbessern. Beim Konvertieren der Liste in einen Binärbaum wird Hashcode als Verzweigungsvariable verwendet. Wenn sich zwei verschiedene Hashcodes im selben Bucket befinden, wird einer als größer angesehen und befindet sich rechts vom Baum und der andere links. Wenn jedoch beide Hashcodes gleich sind, wird HashMapdavon ausgegangen, dass die Schlüssel vergleichbar sind, und der Schlüssel wird verglichen, um die Richtung zu bestimmen, damit eine bestimmte Reihenfolge beibehalten werden kann. Es ist eine gute Praxis, die Schlüssel HashMap vergleichbar zu machen . Beim Hinzufügen von Einträgen, wenn die Bucket-Größe erreicht istTREEIFY_THRESHOLD = 8Konvertieren Sie die verknüpfte Liste von Einträgen in einen ausgeglichenen Baum. Wenn Sie Einträge entfernen, die kleiner als TREEIFY_THRESHOLD und höchstens sind, UNTREEIFY_THRESHOLD = 6wird der ausgeglichene Baum wieder in eine verknüpfte Liste von Einträgen konvertiert . Java 8 SRC , Stackpost

« Iteration der Sammlungsansicht, ausfallsicher und ausfallsicher

    +--------------------+-----------+-------------+
    |                    | Iterator  | Enumeration |
    +--------------------+-----------+-------------+
    | Hashtable          | fail-fast |    safe     |
    +--------------------+-----------+-------------+
    | HashMap            | fail-fast | fail-fast   |
    +--------------------+-----------+-------------+
    | ConcurrentHashMap  |   safe    |   safe      |
    +--------------------+-----------+-------------+

Iteratorist ein Fail-Fast in der Natur. Das heißt, es wird eine ConcurrentModificationException ausgelöst, wenn eine Sammlung geändert wird, während eine andere als die eigene remove () -Methode iteriert wird. Wo wie Enumerationin der Natur ausfallsicher ist. Es werden keine Ausnahmen ausgelöst, wenn eine Sammlung während der Iteration geändert wird.

Laut Java API Docs wird Iterator immer der Aufzählung vorgezogen.

HINWEIS: Die Funktionalität der Enumeration-Schnittstelle wird von der Iterator-Schnittstelle dupliziert. Darüber hinaus fügt Iterator eine optionale Entfernungsoperation hinzu und verfügt über kürzere Methodennamen. Neue Implementierungen sollten die Verwendung von Iterator anstelle von Enumeration in Betracht ziehen.

In Java 5 wurde die ConcurrentMap-Schnittstelle eingeführt : ConcurrentHashMap- Eine hochkonkurrierende, leistungsstarke ConcurrentMapImplementierung, die von einer Hash-Tabelle unterstützt wird. Diese Implementierung wird beim Abrufen niemals blockiert und ermöglicht es dem Client, die Parallelitätsstufe für Aktualisierungen auszuwählen. Es ist als Ersatz für Folgendes gedacht Hashtable: Zusätzlich zur Implementierung ConcurrentMapunterstützt es alle "Legacy" -Methoden, die es gibt Hashtable.

  • Jeder HashMapEntrys-Wert ist flüchtig, wodurch eine feine Kornkonsistenz für konkurrierende Modifikationen und nachfolgende Lesevorgänge sichergestellt wird. Jeder Lesevorgang spiegelt das zuletzt abgeschlossene Update wider

  • Iteratoren und Aufzählungen sind ausfallsicher - spiegeln den Status zu einem bestimmten Zeitpunkt seit der Erstellung des Iterators / der Aufzählung wider. Dies ermöglicht gleichzeitiges Lesen und Ändern auf Kosten einer verringerten Konsistenz. Sie lösen keine ConcurrentModificationException aus. Iteratoren können jedoch jeweils nur von einem Thread verwendet werden.

  • Wie, Hashtableaber HashMapnicht, erlaubt diese Klasse nicht, dass Null als Schlüssel oder Wert verwendet wird.

public static void main(String[] args) {

    //HashMap<String, Integer> hash = new HashMap<String, Integer>();
    Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
    //ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();

    new Thread() {
        @Override public void run() {
            try {
                for (int i = 10; i < 20; i++) {
                    sleepThread(1);
                    System.out.println("T1 :- Key"+i);
                    hash.put("Key"+i, i);
                }
                System.out.println( System.identityHashCode( hash ) );
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();
    new Thread() {
        @Override public void run() {
            try {
                sleepThread(5);
                // ConcurrentHashMap  traverse using Iterator, Enumeration is Fail-Safe.

                // Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
                for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ e.nextElement());
                }

                // HashMap traverse using Iterator, Enumeration is Fail-Fast.
                /*
                for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ it.next());
                    // ConcurrentModificationException at java.util.Hashtable$Enumerator.next
                }
                */

                /*
                Set< Entry<String, Integer> > entrySet = hash.entrySet();
                Iterator< Entry<String, Integer> > it = entrySet.iterator();
                Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
                while( entryEnumeration.hasMoreElements() ) {
                    sleepThread(1);
                    Entry<String, Integer> nextElement = entryEnumeration.nextElement();
                    System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
                    //java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
                    //                                          at java.util.HashMap$EntryIterator.next
                    //                                          at java.util.Collections$3.nextElement
                }
                */
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();

    Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
    try {
        unmodifiableMap.put("key4", "unmodifiableMap");
    } catch (java.lang.UnsupportedOperationException e) {
        System.err.println("UnsupportedOperationException : "+ e.getMessage() );
    }
}
static void sleepThread( int sec ) {
    try {
        Thread.sleep( 1000 * sec );
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

« Nullschlüssel und Nullwerte

HashMaperlaubt maximal einen Nullschlüssel und eine beliebige Anzahl von Nullwerten. Wenn as Hashtablenicht einmal einen einzelnen Nullschlüssel und einen Nullwert zulässt, wird, wenn der Schlüssel oder Wert Null ist, eine NullPointerException ausgelöst. Beispiel

« Synchronisiert, threadsicher

Hashtableist intern synchronisiert. Daher ist die Verwendung Hashtablein Multithread-Anwendungen sehr sicher . Wobei as HashMapnicht intern synchronisiert ist. Daher ist die Verwendung HashMapin Multithread-Anwendungen ohne externe Synchronisierung nicht sicher . Sie können HashMapmithilfe der Collections.synchronizedMap()Methode extern synchronisieren .

« Leistung

Da Hashtableintern synchronisiert, macht dies Hashtableetwas langsamer als die HashMap.


@Sehen

Yash
quelle
18

Bei Thread-Apps können Sie häufig mit ConcurrentHashMap davonkommen - abhängig von Ihren Leistungsanforderungen.

Tim Howland
quelle
17

1. Hashmapund HashTablesowohl Speicherschlüssel als auch Wert.

2. Hashmapkann einen Schlüssel als speichern null. Hashtablekann nicht speichern null.

3. HashMapist nicht synchronisiert, sondern Hashtablesynchronisiert.

4. HashMapkann synchronisiert werden mitCollection.SyncronizedMap(map)

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);
Rahul Tripathi
quelle
16

Abgesehen von den bereits erwähnten Unterschieden sollte beachtet werden, dass seit Java 8 HashMapdie in jedem Bucket verwendeten Knoten (verknüpfte Liste) dynamisch durch TreeNodes (rot-schwarzer Baum) ersetzt werden, so dass selbst bei Kollisionen mit hohem Hash der schlimmste Fall vorliegt, wenn suchen ist

O (log (n)) für HashMap Vs O (n) in Hashtable.

* Die oben erwähnte Verbesserung wurde nicht angewandt worden Hashtablenoch, aber nur zu HashMap, LinkedHashMapund ConcurrentHashMap.

Zu Ihrer Information, derzeit

  • TREEIFY_THRESHOLD = 8 : Wenn ein Bucket mehr als 8 Knoten enthält, wird die verknüpfte Liste in einen ausgeglichenen Baum umgewandelt.
  • UNTREEIFY_THRESHOLD = 6 : Wenn ein Bucket zu klein wird (aufgrund von Entfernung oder Größenänderung), wird der Baum wieder in eine verknüpfte Liste konvertiert.
Kostas Chalkias
quelle
14

Bei HashTable und HashMaps gibt es 5 grundlegende Unterscheidungen.

  1. Mit Maps können Sie Schlüssel, Werte und beide Schlüssel-Wert-Paare iterieren und abrufen, wobei HashTable nicht über alle diese Funktionen verfügt.
  2. In Hashtable gibt es eine Funktion enthält (), deren Verwendung sehr verwirrend ist. Weil die Bedeutung von enthält leicht abweicht. Ob es bedeutet, Schlüssel enthält oder Wert enthält? schwer zu verstehen. In Maps haben wir die Funktionen ContainsKey () und ContainsValue (), die sehr einfach zu verstehen sind.
  3. In der Hashmap können Sie Elemente während der Iteration sicher entfernen. wo es in Hashtabellen nicht möglich ist.
  4. HashTables sind standardmäßig synchronisiert, sodass sie problemlos mit mehreren Threads verwendet werden können. Wenn HashMaps standardmäßig nicht synchronisiert sind, kann dies nur mit einem einzelnen Thread verwendet werden. Sie können HashMap jedoch weiterhin in synchronisiert konvertieren, indem Sie die synchronizedMap (Map m) -Funktion der Collections util-Klasse verwenden.
  5. HashTable lässt keine Nullschlüssel oder Nullwerte zu. Wobei HashMap einen Nullschlüssel und mehrere Nullwerte zulässt.
user1923551
quelle
13

Mein kleiner Beitrag:

  1. Der erste und wichtigste Unterschied zwischen Hashtableund HashMapist, dass HashMapes nicht threadsicher ist, während Hashtablees sich um eine threadsichere Sammlung handelt.

  2. Der zweite wichtige Unterschied zwischen Hashtableund HashMapist die Leistung, da sie HashMapnicht synchronisiert ist und eine bessere Leistung aufweist als Hashtable.

  3. Der dritte Unterschied zu Hashtablevs HashMapbesteht darin, dass Hashtablees sich um eine veraltete Klasse handelt, die Sie ConcurrentHashMapanstelle von Hashtablein Java verwenden sollten.

Shreyos Adikari
quelle
11

HashMap: Es handelt sich um eine Klasse, die im Paket java.util verfügbar ist und zum Speichern des Elements im Schlüssel- und Wertformat verwendet wird.

Hashtable: Es handelt sich um eine Legacy-Klasse, die im Collection-Framework erkannt wird.

Ankit
quelle
Wenn dies der Fall ist, sollte es in Kommentaren nicht als Antwort stehen.
Manikant Gautam
10

HashTable ist eine Legacy-Klasse im JDK, die nicht mehr verwendet werden sollte. Ersetzen Sie die Verwendung durch ConcurrentHashMap . Wenn Sie keine Thread-Sicherheit benötigen, verwenden Sie HashMap, das nicht threadsicher, aber schneller ist und weniger Speicher benötigt.

jontejj
quelle
Weil ich dachte, die anderen Antworten hätten HashTable damals nicht verworfen, sondern erklärt, dass es threadsicher sei. Die Wahrheit ist, dass Sie HashTable, sobald Sie es im Code sehen, durch ConcurrentHashMap ersetzen sollten, ohne einen Schlag auszulassen. Und wenn die Thread-Sicherheit keine Rolle spielt, kann HashMap verwendet werden, um die Leistung ein wenig zu verbessern.
Jontejj
10
  1. Hashtableist synchronisiert, während dies HashMapnicht der Fall ist.
  2. Ein weiterer Unterschied besteht darin, dass der Iterator in der HashMapausfallsicher ist, während der Enumerator für die Hashtablenicht ausfallsicher ist. Wenn Sie die Karte während der Iteration ändern, wissen Sie Bescheid.
  3. HashMaperlaubt Nullwerte darin, während Hashtabledies nicht der Fall ist.
Raja
quelle
3
Der HashMap-Iterator ist ausfallsicher und nicht ausfallsicher. Deshalb haben wir ConcurrentHashMap, die Änderungen während der Iteration ermöglicht. Überprüfen Sie diesen Beitrag journaldev.com/122/…
Pankaj
9

HashMap und HashTable

  • Einige wichtige Punkte zu HashMap und HashTable. Bitte lesen Sie unten Details.

1) Hashtable und Hashmap implementieren die Schnittstelle java.util.Map. 2) Sowohl Hashmap als auch Hashtable sind die Hash-basierte Sammlung. und am Hashing arbeiten. Das sind also Ähnlichkeiten von HashMap und HashTable.

  • Was ist der Unterschied zwischen HashMap und HashTable?

1) Der erste Unterschied ist, dass HashMap nicht threadsicher ist, während HashTable ThreadSafe ist.
2) HashMap ist leistungsmäßig besser, da es nicht threadsicher ist. Die Leistung von Hashtable ist jedoch nicht besser, da sie threadsicher ist. Daher können mehrere Threads nicht gleichzeitig auf Hashtable zugreifen.

JegsVala
quelle
2
Abgestimmt, weil diese Antwort in einigen Aspekten nicht korrekt ist. Hashtable implementiert die Map-Schnittstelle nicht, sondern erweitert nur die veraltete Dictionary-Klasse.
Yannis Sermetziadis
8

Hashtable:

Hashtable ist eine Datenstruktur, die die Werte des Schlüssel-Wert-Paares beibehält. Sowohl für die Schlüssel als auch für die Werte ist keine Null zulässig. Sie erhalten einen, NullPointerExceptionwenn Sie einen Nullwert hinzufügen. Es ist synchronisiert. Es kommt also mit seinen Kosten. Zu einem bestimmten Zeitpunkt kann nur ein Thread auf HashTable zugreifen .

Beispiel :

import java.util.Map;
import java.util.Hashtable;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states= new Hashtable<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    //will throw NullPointerEcxeption at runtime

    System.out.println(states.get(1));
    System.out.println(states.get(2));
//  System.out.println(states.get(3));

    }
}

HashMap:

HashMap ähnelt Hashtable , akzeptiert jedoch auch Schlüsselwertpaare. Es erlaubt null sowohl für die Schlüssel als auch für die Werte. Seine Leistung ist besser als HashTable, weil es ist unsynchronized.

Beispiel:

import java.util.HashMap;
import java.util.Map;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states = new HashMap<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    // Okay
    states.put(null,"UK");

    System.out.println(states.get(1));
    System.out.println(states.get(2));
    System.out.println(states.get(3));

    }
}
IntelliJ Amiya
quelle
5

HashMapwird emuliert und kann daher verwendet werden, GWT client codewährend dies Hashtablenicht der Fall ist.

Pong
quelle
Ist das eine umfassende Beschreibung der Unterschiede zwischen den beiden Apis?
IgorGanapolsky
Ja (sic!). Das ist alles, was GWT-Entwickler darüber wissen müssen.
Pong
5

Altes und klassisches Thema, möchte nur diesen hilfreichen Blog hinzufügen, der dies erklärt:

http://blog.manishchhabra.com/2012/08/the-5-main-differences-betwen-hashmap-and-hashtable/

Blog von Manish Chhabra

Die 5 Hauptunterschiede zwischen HashMap und Hashtable

HashMap und Hashtable implementieren beide die Schnittstelle java.util.Map, aber es gibt einige Unterschiede, die Java-Entwickler verstehen müssen, um effizienteren Code zu schreiben. Ab der Java 2-Plattform v1.2 wurde die Hashtable-Klasse nachgerüstet, um die Map-Schnittstelle zu implementieren, sodass sie Mitglied des Java Collections Framework ist.

  1. Einer der Hauptunterschiede zwischen HashMap und Hashtable besteht darin, dass HashMap nicht synchronisiert ist, während Hashtable synchronisiert ist. Dies bedeutet, dass Hashtable threadsicher ist und von mehreren Threads gemeinsam genutzt werden kann, HashMap jedoch nicht ohne ordnungsgemäße Synchronisierung von mehreren Threads gemeinsam genutzt werden kann. In Java 5 wurde ConcurrentHashMap eingeführt, eine Alternative zu Hashtable, die eine bessere Skalierbarkeit als Hashtable in Java bietet. Synchronisiert bedeutet, dass nur ein Thread eine Hash-Tabelle zu einem bestimmten Zeitpunkt ändern kann. Grundsätzlich bedeutet dies, dass jeder Thread vor dem Aktualisieren einer Hashtabelle eine Sperre für das Objekt erhalten muss, während andere darauf warten, dass die Sperre aufgehoben wird.

  2. Die HashMap-Klasse entspricht in etwa Hashtable, außer dass sie Nullen zulässt. (HashMap erlaubt Nullwerte als Schlüssel und Wert, während Hashtable keine Nullen zulässt.)

  3. Der dritte signifikante Unterschied zwischen HashMap und Hashtable besteht darin, dass Iterator in der HashMap ein ausfallsicherer Iterator ist, während der Enumerator für die Hashtable dies nicht ist, und ConcurrentModificationException auslöst, wenn ein anderer Thread die Map strukturell ändert, indem er ein Element außer Iterators eigenem Entfernen hinzufügt oder entfernt ( ) Methode. Dies ist jedoch kein garantiertes Verhalten und wird von JVM nach besten Kräften durchgeführt. Dies ist auch ein wichtiger Unterschied zwischen Enumeration und Iterator in Java.

  4. Ein weiterer bemerkenswerter Unterschied zwischen Hashtable und HashMap besteht darin, dass Hashtable aufgrund der Thread-Sicherheit und -Synchronisation viel langsamer als HashMap ist, wenn es in einer Single-Thread-Umgebung verwendet wird. Wenn Sie also keine Synchronisation benötigen und HashMap nur von einem Thread verwendet wird, führt es Hashtable in Java aus.

  5. HashMap garantiert nicht, dass die Reihenfolge der Karte über die Zeit konstant bleibt.

Beachten Sie, dass HashMap von synchronisiert werden kann

Map m = Collections.synchronizedMap(hashMap);

Zusammenfassend gibt es signifikante Unterschiede zwischen Hashtable und HashMap in Java, z. B. Thread-Sicherheit und Geschwindigkeit. Basierend darauf verwenden Sie Hashtable nur, wenn Sie unbedingt Thread-Sicherheit benötigen. Wenn Sie Java 5 ausführen, sollten Sie ConcurrentHashMap in Java verwenden.

Nacht0
quelle
ConcurrentHashMap ist nicht lesesynchronisiert, Hashtable dagegen. Wenn also eine große Anzahl von Lesevorgängen gleichzeitig mit Schreibvorgängen ausgeführt wird, ist eine Hashtable für Sie besser geeignet, wenn Sie sich um die Datenintegrität kümmern.
Igor Ganapolsky
5

HashMap und Hashtable werden beide zum Speichern von Daten in Schlüssel- und Wertform verwendet. Beide verwenden die Hashing-Technik, um eindeutige Schlüssel zu speichern. Es gibt jedoch viele Unterschiede zwischen den unten angegebenen HashMap- und Hashtable-Klassen.

Geben Sie hier die Bildbeschreibung ein

DeC
quelle
Schöne visuelle Zusammenfassung!
Nadjib Mami