Pytanie Różnice między HashMap i HashTable?


Jakie są różnice między a HashMap i a Hashtable w Javie?

Co jest bardziej wydajne w aplikacjach bez gwintu?


3122
2017-09-02 20:12


pochodzenie


HashTable jest przestarzałe w Javie 1.7 i zaleca się stosowanie implementacji ConcurrentMap - MissFiona


Odpowiedzi:


Istnieje kilka różnic między HashMap i Hashtable w Javie:

  1. Hashtable jest zsynchronizowany, natomiast HashMap nie jest. To sprawia HashMap lepiej dla aplikacji bez wątków, ponieważ niezsynchronizowane obiekty zazwyczaj działają lepiej niż zsynchronizowane.

  2. Hashtable nie pozwala null klucze lub wartości. HashMap pozwala jeden null klucz i dowolna liczba null wartości.

  3. Jedną z podklas HashMap jest LinkedHashMap, więc jeśli chcesz mieć przewidywalną kolejność iteracji (domyślnie jest to zamówienie reklamowe), możesz łatwo zamienić HashMap dla LinkedHashMap. To nie byłoby takie proste, gdybyś używał Hashtable.

Ponieważ synchronizacja nie jest dla ciebie problemem, polecam HashMap. Jeśli synchronizacja staje się problemem, możesz również przyjrzeć się ConcurrentHashMap.


3207
2017-09-02 23:02



Jeśli chcesz utworzyć wątek HashMap, użyj Collections.synchronizedMap(). - Rok Strniša
Chciałbym również skomentować to naiwne podejście do bezpieczeństwa gwintów w Hashtable ("synchronizacja każdej metody powinna zająć się wszelkimi problemami współbieżności!") sprawia, że ​​jest bardzo gorzej dla aplikacji gwintowanych. Lepiej zsynchronizuj zewnętrznie a HashMap(i myśląc o konsekwencjach) lub używając a ConcurrentMap implementacja (i wykorzystanie jej rozszerzonego API dla współbieżności). Konkluzja: jedyny powód do użycia Hashtable jest wtedy, gdy wymaga tego starsza wersja API (od ok. 1996). - erickson
HashMap daje programistom możliwość pisania kodu ThreadSafe, gdy faktycznie go używają. Rzadko zdarzało mi się, że potrzebowałem kolekcji bezpiecznej dla wątków, takiej jak ConcurrentHashMap lub HashTable. Potrzebowałem pewnego zestawu funkcji lub pewnych instrukcji w zsynchronizowanym bloku, aby być bezpiecznym dla wątków. - Gaurava Agarwal
HashTable jest przestarzała i używamy HashMap dla środowiska bez wątków. Jeśli potrzebujesz bezpieczeństwa wątku, możesz użyć Collections.synchronizedMap () lub użyć ConcurrentHashMap, który jest bardziej wydajny niż hashtable. - Maneesh Kumar
Jest przestarzały, ale nie przestarzały i zastanawiam się, dlaczego tak jest. Zgaduję, że usunięcie tej klasy (i Vector z tych samych powodów) złamie zbyt wiele istniejącego kodu, a adnotacja z @Deprecated oznaczałaby zamiar usunięcia kodu, którego najwyraźniej nie ma. - Jilles van Gurp


Zauważ, że wiele odpowiedzi stwierdza, że ​​HashTable jest zsynchronizowane. W praktyce kupuje to bardzo mało.  Synchronizacja na metodach accessor / mutator zatrzyma dwa wątki dodawania lub usuwania jednocześnie z mapy, ale w świecie rzeczywistym często potrzebna jest dodatkowa synchronizacja.

Bardzo popularnym idiomem jest "sprawdź, a następnie umieść" - tzn. Poszukaj wpisu na mapie i dodaj go, jeśli jeszcze nie istnieje. Nie jest to żadna operacja atomowa, niezależnie od tego, czy używasz Hashtable, czy HashMap.

Równoważnie zsynchronizowany HashMap można uzyskać przez:

Collections.synchronizedMap(myMap);

Ale aby poprawnie wdrożyć tę logikę, potrzebujesz dodatkowa synchronizacja formularza:

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

Nawet iteracja wpisów Hashtable (lub HashMap uzyskanych przez Collections.synchronizedMap) nie jest bezpieczna dla wątków, chyba że chronisz także Mapę przed modyfikacją poprzez dodatkową synchronizację.

Wdrożenia ConcurrentMap interfejs (na przykład ConcurrentHashMap) rozwiązać niektóre z nich poprzez włączenie semantyka sprawdzania i kontynuowania wątku Jak na przykład:

ConcurrentMap.putIfAbsent(key, value);

583
2017-09-03 11:00



Zwróć także uwagę, że jeśli modyfikowana jest HashMap, to iteratory wskazujące na to, stają się nieważne. - Chris K
Iterator rzuci ConcurrentModificationException, prawda? - Bhushan
Czy jest jakaś różnica między zsynchronizowanymi (myMap) {...} i ConcurrentHashMap pod względem bezpieczeństwa wątków? - telebog
To prawda, próbowałem to wyjaśnić tutaj ...lovehasija.com/2012/08/16/... - Love Hasija
@Bhushan: Przyniesie to najlepszy wysiłek, to nie jest gwarantowane zachowanie: docs.oracle.com/javase/7/docs/api/java/util/HashMap.html - Matt Stephenson


Hashtable jest uważany za starszy kod. Nie ma nic w tym Hashtable nie można tego zrobić za pomocą HashMap lub pochodne HashMap, więc dla nowego kodu, nie widzę żadnego uzasadnienia dla powrotu Hashtable.


288
2018-06-25 01:46



Z Jastrzębi Hashtable (dodano naciski): "Od wersji platformy Java 2 w wersji 1.2 ta klasa została zmodernizowana w celu implementacji interfejsu Map, co czyni go członkiem Java Collections Framework"Jednakże masz rację, że jest to starszy kod, wszystkie korzyści z synchronizacji można uzyskać bardziej efektywnie dzięki Collections.synchronizedMap (HashMap). (Podobnie jak Vector będący starszą wersją Collections.synchronizedList (ArrayList).) - Kip
@ aberrant80: niestety nie masz wyboru między tymi dwoma i musisz używać Hashtable podczas programowania J2ME ... - pwes
tę odpowiedź należy usunąć. zawiera niepoprawne informacje i ma dużo przebojów. - anon58192932
@ Anon58192932 Czy można edytować pytanie, aby to naprawić? - GC_
Musimy zwrócić uwagę plakatu @ aberrant80 lub administratora poprzez oflagowanie. Zgłaszanie może pomóc - spróbuje teraz. - anon58192932


To pytanie jest często zadawane w trakcie wywiadu, aby sprawdzić, czy kandydat rozumie prawidłowe użycie klas kolekcji i ma świadomość dostępnych alternatywnych rozwiązań.

  1. Klasa HashMap jest mniej więcej odpowiednikiem Hashtable, z tym, że jest niezsynchronizowana i dopuszcza wartości null. (HashMap zezwala na wartości puste jako klucz i wartość, podczas gdy Hashtable nie dopuszcza wartości null).
  2. HashMap nie gwarantuje, że kolejność map pozostanie stała w czasie.
  3. HashMap nie jest zsynchronizowany, a HashTable jest zsynchronizowany.
  4. Iterator w HashMap jest odporny na awarie, podczas gdy moduł wyliczający dla HashTable nie jest i rzutuje ConcurrentModificationException, jeśli jakikolwiek inny wątek modyfikuje mapę w sposób strukturalny, dodając lub usuwając dowolny element poza własną metodą remove () Iteratora. Ale nie jest to zachowanie gwarantowane i zostanie wykonane przez JVM na najlepszy wysiłek.

Uwaga na temat niektórych ważnych warunków

  1. Zsynchronizowane oznacza, że ​​tylko jeden wątek może zmodyfikować tabelę mieszania w pewnym momencie. Zasadniczo oznacza to, że każdy wątek przed wykonaniem aktualizacji na hoście musi zdobyć blokadę obiektu, podczas gdy inni będą czekać na zwolnienie blokady.
  2. Fail-safe ma znaczenie z kontekstu iteratorów. Jeśli w obiekcie kolekcji został utworzony iterator, a inny wątek próbuje zmodyfikować obiekt kolekcji "strukturalnie", zostanie zgłoszony wyjątek dotyczący mody współbieżnej. Możliwe jest jednak, że inne wątki wywołują metodę "set", ponieważ nie modyfikują kolekcji "strukturalnie". Jednakże, jeśli przed wywołaniem "zestaw", kolekcja została zmodyfikowana strukturalnie, "IllegalArgumentException" zostanie zgłoszony.
  3. Modyfikacja strukturalna oznacza usunięcie lub wstawienie elementu, który mógłby skutecznie zmienić strukturę mapy.

HashMap może być synchronizowany przez

Map m = Collections.synchronizeMap(hashMap);

Mapa zapewnia widoki kolekcji zamiast bezpośredniego wsparcia dla iteracji  za pośrednictwem obiektów Enumeration. Widoki kolekcji znacznie zwiększają  ekspresyjność interfejsu, jak omówiono w dalszej części tej sekcji.  Mapa pozwala na iterację kluczy, wartości lub par klucz-wartość;  Hashtable nie zapewnia trzeciej opcji. Mapa zapewnia bezpieczny sposób  usuwać wpisy pośród iteracji; Hashtable nie.  Wreszcie Map naprawia niewielki niedostatek interfejsu HashTable.  Hashtable ma metodę o nazwie contains, która zwraca wartość true, jeśli  Hashtable zawiera określoną wartość. Biorąc pod uwagę jego nazwę, można się tego spodziewać  metoda zwracania wartości true, jeśli tablica Hashtable zawierała dany klucz, ponieważ  klucz jest podstawowym mechanizmem dostępu do HashTable. Mapa  Interfejs eliminuje to źródło nieporozumień poprzez zmianę nazwy metody  containsValue. Ponadto poprawia to spójność interfejsu -  zawiera paralele Wartość zawiera klucz.

Interfejs mapy


148
2017-10-04 06:39



Ta odpowiedź zawiera co najmniej 2 istotne nieścisłości faktograficzne. Z pewnością NIE zasługuje na tak wiele upiorów. - Stephen C
1) Iteratory HashMap NIE są bezpieczne. Są odporne na awarie. Między tymi dwoma terminami istnieje ogromna różnica w znaczeniu. 2) Nie ma set operacja na HashMap. 3) put(...) operacja nie będzie rzucać IllegalArgumentException jeśli była poprzednia zmiana. 4) Nieprzestrzeganie błędów w działaniu HashMap  również występuje, jeśli zmienisz mapowanie. 5) Szybkie zachowanie jest gwarantowane. (Nie jest gwarantowane zachowanie się a HashTablejeśli dokonasz jednoczesnej modyfikacji. Rzeczywiste zachowanie jest ... nieprzewidywalne.) - Stephen C
6) Hashtable nie gwarantuje, że kolejność elementów mapy będzie z czasem stabilna. (Być może jesteś mylący Hashtable z LinkedHashMap.) - Stephen C
Czy ktoś jeszcze naprawdę martwił się, że studenci mają obecnie błędny pomysł, że uzyskanie "zsynchronizowanych wersji" kolekcji w jakiś sposób oznacza, że ​​nie trzeba zewnętrznie synchronizować operacji złożonych? Mój ulubiony przykład tego istnienia thing.set(thing.get() + 1); które częściej niż inni łapią nowinki z zaskoczenia jako całkowicie niechronione, szczególnie jeśli get() i set() są zsynchronizowane metody. Wielu z nich oczekuje magii.
Iteratory w HashMap nie są bezpieczne w razie awarii - Abdul


HashMap: Implementacja Map interfejs używający kodów mieszających do indeksowania tablicy. Hashtable: Cześć, 1998 zadzwonił. Chcą odzyskać swój interfejs API.

Poważnie, lepiej jest trzymać się z daleka Hashtable całkowicie. W przypadku aplikacji jednowątkowych nie potrzebujesz dodatkowego obciążenia synchronizacji. W przypadku bardzo równoczesnych aplikacji synchronizacja paranoiczna może prowadzić do zagłodzenia, zakleszczenia lub zbędnego zbierania śmieci. Jak wskazał Tim Howland, możesz użyć ConcurrentHashMap zamiast.


107
2017-09-02 23:14



To ma sens. ConcurrentHashMaps zapewnia swobodę synchronizacji, a debugowanie jest o wiele łatwiejsze. - prap19


Weź pod uwagę, że HashTable była wcześniejsza klasa przed wprowadzeniem Java Collections Framework (JCF) i została później zmodernizowana w celu implementacji Map berło. Więc był Vector i Stack.

Dlatego zawsze trzymaj się z dala od nich w nowym kodzie, ponieważ zawsze istnieje lepsza alternatywa w JCF jak zauważyli inni.

Tutaj jest Arkusz ściągania kolekcji Java które okaże się przydatne. Zauważ, że szary blok zawiera starszą klasę HashTable, Vector i Stack.

enter image description here


104
2018-03-25 08:58





Oprócz tego, co powiedział izb, HashMap dopuszcza wartości puste, podczas gdy Hashtablenie.

Zwróć też uwagę na to Hashtable przedłuża Dictionary klasa, która jako Javadocs jest przestarzały i został zastąpiony przez Map berło.


58
2017-09-02 20:30



ale to nie sprawia, że ​​HashTable jest przestarzałe? - Pacerier


Spójrz na tę tabelę. Zapewnia porównanie różnych struktur danych wraz z HashMap i HashTable. Porównanie jest precyzyjne, jasne i łatwe do zrozumienia.

Java Collection Matrix


50
2017-11-20 05:35



dzięki, teraz wiem, co wybrać w moim scenariuszu. - Well Smith


Hashtable jest podobny do HashMap i ma podobny interfejs. Zaleca się, aby użyć HashMap, chyba że potrzebujesz wsparcia dla starszych aplikacji lub potrzebujesz synchronizacji, jako Hashtables metody są zsynchronizowane. W twoim przypadku, ponieważ nie jesteś wielowątkowy, HashMaps jesteś najlepszy.


39
2017-09-02 20:25





Inną kluczową różnicą między hashtable i hashmap jest to, że Iterator w HashMap jest szybki, podczas gdy moduł wyliczający dla HashTable nie jest i rzutuje ConcurrentModificationException, jeśli jakikolwiek inny wątek modyfikuje mapę strukturalnie przez dodanie lub usunięcie dowolnego elementu z wyjątkiem metody iteratora (). Ale nie jest to zachowanie gwarantowane i zostanie wykonane przez JVM na najlepszy wysiłek ".

Moje źródło: http://javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html


31
2017-09-08 06:40





Istnieje już wiele dobrych odpowiedzi. Dodaję kilka nowych punktów i podsumowuję to.

HashMap i Hashtable oba są używane do przechowywania dane w formie klucza i wartości. Obie używają techniki haszowania do przechowywania unikalnych kluczy. Istnieje jednak wiele różnic między klasami HashMap i Hashtable, które podano poniżej.

HashMap 

1) HashMap jest niezsynchronizowany. Nie jest bezpieczna dla wątków i nie może być współdzielona między wieloma wątkami bez odpowiedniego kodu synchronizacji.
2) HashMap zezwala na jeden pusty klucz i wiele wartości pustych.
3) HashMap to nowa klasa wprowadzona w JDK 1.2.
4) HashMap jest szybki.
5) Możemy zrobić HashMap zsynchronizowane przez wywołanie tego kodu
Map m = Collections.synchronizedMap(HashMap);
6) HashMap przechodzi przez Iterator.
7) Iterator w HashMap działa szybko.
8) HashMap dziedziczy klasę AbstractMap.

Hashtable

1) Hashtable jest zsynchronizowany. Jest bezpieczny dla wątków i może być współdzielony z wieloma wątkami.
2) Hashtable nie zezwala na żaden pusty klucz ani wartość.
3) Hashtable jest starszą klasą.
4) Hashtable jest wolny.
5) Hashtable jest wewnętrznie zsynchronizowany i nie może być niezsynchronizowany.
6) Hashtable jest przesuwany przez Enumerator i Iterator.
7) Moduł wyliczający w Hashtable nie jest szybki.
8) Hashtable dziedziczy klasę Dictionary.

Dalsze czytanie Jaka jest różnica między HashMap i Hashtable w Javie?

enter image description here


31
2018-03-06 10:09



Prawie w tej odpowiedzi (duplikat) - stackoverflow.com/a/39785829/432903. - prayagupd
Dlaczego mówisz ~ "Hashtable to starsza klasa"Gdzie jest dokumentacja pomocnicza do tego. - Igor Ganapolsky
@IgorGanapolsky możesz przeczytać to - stackoverflow.com/questions/21086307/... - roottraveller
Utrzymywanie HashMap jest kosztowne niż TreeMap. Ponieważ HashMap tworzy niepotrzebne dodatkowe segmenty. - Abdul