Różnice między HashMap i Hashtable?


3749

Jakie są różnice między HashMapa a Hashtablew Javie?

Który z nich jest bardziej wydajny w zastosowaniach bez wątków?


17
HashTable jest przestarzały w Javie 1.7 i zaleca się korzystanie z implementacji ConcurrentMap
MissFiona

@MissFiona Nie, ConcurrentMaptutaj nie jest konieczne, ponieważ w pytaniu jest napisane: „aplikacje bez wątków”, co oznacza, że ​​wątkowanie / współbieżność nie stanowi problemu.
Basil Bourque

Odpowiedzi:


3773

Istnieje kilka różnic między HashMapi Hashtablew Javie:

  1. Hashtablejest zsynchronizowany , ale HashMapnie jest. To sprawia, że HashMaplepiej jest dla aplikacji bez wątków, ponieważ Obiekty niezsynchronizowane zwykle działają lepiej niż te zsynchronizowane.

  2. Hashtablenie zezwala na nullklucze ani wartości. HashMappozwala na jeden nullklucz i dowolną liczbę nullwartości.

  3. Jedną z podklas HashMap jest LinkedHashMap, więc jeśli chcesz mieć przewidywalną kolejność iteracji (która domyślnie jest kolejnością wstawiania), możesz łatwo zamienić HashMapna LinkedHashMap. Nie byłoby to takie proste, gdybyś używał Hashtable.

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


84
Jeśli chcesz, aby HashMap był bezpieczny dla wątków, użyj Collections.synchronizedMap().
Rok Strniša

275
Chciałbym również skomentować, że naiwne podejście do bezpieczeństwa wątków w Hashtable(„synchronizowanie każdej metody powinno zadbać o wszelkie problemy z współbieżnością!”) Znacznie pogarsza to w przypadku aplikacji wątkowych. Lepiej zsynchronizuj zewnętrznie HashMap(i myśląc o konsekwencjach) lub skorzystaj z ConcurrentMapimplementacji (i wykorzystaj jej rozszerzony interfejs API do współbieżności). Podsumowując: jedynym powodem do użycia Hashtablejest to, że wymaga tego starszy interfejs API (od ok. 1996 r.).
erickson

8
HashMap daje programistom elastyczność w pisaniu kodu threadSafe, kiedy faktycznie go używają. Rzadko zdarzało się, że potrzebowałem bezpiecznej kolekcji 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

2
Hashtable jest przestarzały i używamy HashMap dla środowiska nie bezpiecznego dla wątków. Jeśli potrzebujesz bezpieczeństwa wątków, możesz użyć Collect.synchronizedMap () lub ConcurrentHashMap, który jest bardziej wydajny niż hashtable.
Maneesh Kumar

1
Jest przestarzały, ale nie przestarzały i zastanawiam się, dlaczego tak jest. Domyślam się, że usunięcie tej klasy (i Vector z tych samych powodów) złamałoby zbyt wiele istniejącego kodu, a adnotacje z @Deprecated oznaczałyby zamiar usunięcia kodu, który najwyraźniej go nie ma.
Jilles van Gurp

682

Zauważ, że wiele odpowiedzi mówi, że Hashtable jest zsynchronizowany. W praktyce to niewiele kosztuje. Synchronizacja jest na metodach akcesor / mutator, aby zatrzymać jednoczesne dodawanie lub usuwanie wątków z mapy, ale w prawdziwym świecie często będziesz potrzebować dodatkowej synchronizacji.

Bardzo popularnym idiomem jest „sprawdź, a następnie umieść” - tj. Poszukaj wpisu w Mapi dodaj go, jeśli jeszcze nie istnieje. Nie jest to w żaden sposób operacja atomowa, niezależnie od tego, czy używasz, Hashtableczy HashMap.

Równoważnie zsynchronizowane HashMapmożna uzyskać poprzez:

Collections.synchronizedMap(myMap);

Ale aby poprawnie zaimplementować tę logikę, potrzebujesz dodatkowej synchronizacji formularza:

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

Nawet iteracja Hashtablewpisów (lub HashMapuzyskanych przez Collections.synchronizedMap) nie jest bezpieczna dla wątków, chyba że zabezpieczysz je również Mapprzed modyfikacją poprzez dodatkową synchronizację.

Implementacje ConcurrentMapinterfejsu (na przykład ConcurrentHashMap) rozwiązują niektóre z tych problemów, włączając w to semantykę bezpiecznego sprawdzania, a następnie działania wątków, takich jak:

ConcurrentMap.putIfAbsent(key, value);

53
Należy również pamiętać, że jeśli zmodyfikowana zostanie HashMap, iteratory wskazujące na nią zostaną unieważnione.
Chris K

3
Czy jest jakaś różnica między synchronizowanym (myMap) {...} a ConcurrentHashMap pod względem bezpieczeństwa wątków?
telebog 11.11.11

3
Bardzo prawda, próbowałem wyjaśnić to samo tutaj .. lovehasija.com/2012/08/16/…
Love Hasija

@Bushushan: Będzie się starał, to nie jest gwarantowane zachowanie: docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
Matt Stephenson

Będąc w środku ekipy programistów JVM od wielu lat, mogę stwierdzić, że wewnętrzna synchronizacja Hashtable jest co najmniej przydatna do prawidłowego wskazywania palcem na kod klienta, gdy pisze nieprzyzwoity kod współbieżny. Otrzymaliśmy kilka skarg na awarie w HashMap (a zatem „oczywiście” błąd JDK / JVM), gdy przyczyną była jednoczesna modyfikacja.
Hot Licks,

363

Hashtablejest uważany za starszy kod. Nic nie Hashtablemożna tego zrobić za pomocą HashMapani pochodnych HashMap, więc dla nowego kodu nie widzę żadnego uzasadnienia dla powrotu do Hashtable.


101
Z Hashtable javadoc (wyróżnienie dodane): „Począwszy od platformy Java 2 v1.2, ta klasa została zmodernizowana w celu implementacji interfejsu Map, co czyni ją członkiem środowiska Java Collections Framework ”. Masz jednak rację, że jest to starszy kod. Wszystkie zalety synchronizacji można uzyskać bardziej efektywnie za pomocą Collections.synchronizedMap (HashMap). (Podobny do Vector jest starszą wersją Collections.synchronizedList (ArrayList).)
Kip

15
@ aberrant80: niestety nie masz wyboru między tymi dwoma i musisz używać Hashtable podczas programowania dla J2ME ...
pwes

6
ta odpowiedź powinna zostać usunięta. zawiera nieprawidłowe informacje i ma wiele pozytywnych opinii.
anon58192932

@ anon58192932 Czy można edytować pytanie, aby je naprawić?
GC_

1
Musimy zwrócić uwagę na plakat @ aberrant80 lub administratora, oflagowując. Oznaczanie może pomóc - spróbuje teraz.
anon58192932

189

To pytanie jest często zadawane w trakcie wywiadu, aby sprawdzić, czy kandydat rozumie prawidłowe wykorzystanie klas zbiórki i jest świadomy dostępnych alternatywnych rozwiązań.

  1. HashMapKlasa jest z grubsza odpowiednikiem Hashtable, poza tym, że nie jest zsynchronizowany i zezwala na wartości null. ( HashMapzezwala na wartości null jako klucz i wartość, Hashtableale nie zezwala na nulls).
  2. HashMap nie gwarantuje, że kolejność mapy pozostanie stała w czasie.
  3. HashMapnie jest zsynchronizowany, natomiast Hashtablejest zsynchronizowany.
  4. Iterator w HashMapjest odporny na awarie, podczas gdy moduł wyliczający dla Hashtablenie jest, i rzuca, ConcurrentModificationExceptionjeśli jakikolwiek inny Wątek modyfikuje strukturalnie mapę poprzez dodanie lub usunięcie dowolnego elementu oprócz Iteratorwłasnej remove() metody. Nie jest to jednak zachowanie gwarantowane i JVM dołoży wszelkich starań.

Uwaga na niektóre ważne warunki:

  1. Zsynchronizowany oznacza, że ​​tylko jeden wątek może modyfikować tablicę skrótów w jednym momencie. Zasadniczo oznacza to, że każdy wątek przed aktualizacją Hashtablebędzie musiał uzyskać blokadę obiektu, podczas gdy inni będą czekać na zwolnienie blokady.
  2. Odporność na awarie jest istotna w kontekście iteratorów. Jeśli w obiekcie kolekcji utworzono iterator, a jakiś inny wątek próbuje zmodyfikować obiekt kolekcji „strukturalnie”, zostanie zgłoszony wyjątek dotyczący równoczesnej modyfikacji. Możliwe jest jednak, że inne wątki wywołują setmetodę, ponieważ nie modyfikuje ona kolekcji „strukturalnie”. Jeśli jednak przed wywołaniem setkolekcja zostanie zmodyfikowana strukturalnie, IllegalArgumentExceptionzostanie wyrzucona.
  3. Modyfikacja strukturalna oznacza usunięcie lub wstawienie elementu, który mógłby skutecznie zmienić strukturę mapy.

HashMap mogą być synchronizowane przez

Map m = Collections.synchronizeMap(hashMap);

Mapa zapewnia widoki kolekcji zamiast bezpośredniej obsługi iteracji za pomocą obiektów wyliczenia. Widoki kolekcji znacznie zwiększają ekspresję interfejsu, co omówiono w dalszej części tego rozdziału. Mapa pozwala na iterację kluczy, wartości lub par klucz-wartość; Hashtablenie zapewnia trzeciej opcji. Mapa zapewnia bezpieczny sposób usuwania wpisów w trakcie iteracji; Hashtablenie. Wreszcie, mapa naprawia niewielki brak Hashtableinterfejsu. Hashtablema metodę o nazwie zawiera, która zwraca wartość true, jeśli Hashtablezawiera określoną wartość. Biorąc pod uwagę jego nazwę, można oczekiwać, że ta metoda zwróci true, jeśli Hashtablezawiera dany klucz, ponieważ klucz jest podstawowym mechanizmem dostępu dla Hashtable. Interfejs mapy eliminuje to źródło nieporozumień, zmieniając nazwę metody containsValue. Poprawia to również spójność interfejsu - containsValuerównolegle containsKey.

Interfejs mapy


19
Ta odpowiedź zawiera co najmniej 2 znaczące nieścisłości faktyczne. Z pewnością NIE Zasługuje na tak wiele pozytywnych opinii.
Stephen C

58
1) Iteratory HashMap NIE są bezpieczne. Są niezawodne. Istnieje ogromna różnica znaczenia między tymi dwoma terminami. 2) Brak setoperacji na HashMap. 3) put(...)Operacja nie zostanie rzucona, IllegalArgumentExceptionjeśli nastąpiła poprzednia zmiana. 4) Zachowanie szybkie w przypadku awarii występuje HashMap również po zmianie mapowania. 5) Gwarantowane jest szybkie działanie . (Nie można zagwarantować zachowania HashTablerównoczesnej modyfikacji. Rzeczywiste zachowanie jest ... nieprzewidywalne.)
Stephen C

25
6) Hashtablenie gwarantuje też, że kolejność elementów mapy będzie stabilna w czasie. (Być może mylisz Hashtablesię LinkedHashMap.)
Stephen C

4
Czy ktoś jeszcze bardzo martwił się, że uczniowie mają obecnie błędny pomysł, że uzyskanie „zsynchronizowanych wersji” kolekcji oznacza w jakiś sposób, że nie trzeba zewnętrznie synchronizować operacji złożonych? Moim ulubionym przykładem tej istoty thing.set(thing.get() + 1);, które częściej niż nie łapie debiutantom przez zaskoczenie jako całkowicie bezbronny, zwłaszcza jeśli get()i set()są zsynchronizowane metod. Wielu z nich oczekuje magii.

Iteratory na HashMap nie są niezawodne
Abdul

130

HashMap: Implementacja Mapinterfejsu używającego kodów skrótu do indeksowania tablicy. Hashtable: Cześć, 1998 dzwonił. Chcą z powrotem interfejsu API swoich kolekcji.

Poważnie, jednak lepiej trzymać się z daleka Hashtable. W przypadku aplikacji jednowątkowych nie potrzebujesz dodatkowych kosztów synchronizacji. W przypadku wysoce współbieżnych aplikacji synchronizacja paranoiczna może prowadzić do głodu, impasu lub niepotrzebnych przerw w usuwaniu elementów bezużytecznych. Jak wskazał Tim Howland, możesz użyć ConcurrentHashMapzamiast tego.


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

1
Czy jest to specyficzne dla Javy lub całej implementacji mapy skrótu.

125

Należy pamiętać, że HashTablebyła to starsza klasa przed wprowadzeniem Java Collections Framework (JCF), a później została zmodernizowana w celu implementacji Mapinterfejsu. Tak było Vectori Stack.

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

Oto ściągawka z kolekcji Java , która okaże się przydatna. Zauważ, że szary blok zawiera starszą klasę HashTable, Vector i Stack.

wprowadź opis zdjęcia tutaj


72

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

HashMapi Hashtableoba służą do przechowywania danych w formie klucza i wartości . Oba używają techniki mieszania do przechowywania unikalnych kluczy. Istnieje jednak wiele różnic między klasami HashMap i Hashtable, które podano poniżej.

HashMap

  1. HashMapnie jest zsynchronizowany. Nie jest bezpieczny dla wątków i nie może być współużytkowany przez wiele wątków bez odpowiedniego kodu synchronizacji.
  2. HashMap dopuszcza jeden klucz zerowy i wiele wartości zerowych.
  3. HashMap to nowa klasa wprowadzona w JDK 1.2.
  4. HashMap jest szybki.
  5. Możemy dokonać HashMapsynchronizacji poprzez wywołanie tego kodu
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap jest trawersowany przez Iterator.
  7. Iterator HashMapjest szybki.
  8. HashMap dziedziczy klasę AbstractMap.

Hashtable

  1. Hashtablejest zsynchronizowany. Jest bezpieczny dla wątków i może być współdzielony z wieloma wątkami.
  2. Hashtable nie zezwala na żaden klucz lub wartość zerową.
  3. Hashtable jest klasą starszą.
  4. Hashtable jest wolny.
  5. Hashtable jest wewnętrznie zsynchronizowany i nie można go zsynchronizować.
  6. Hashtable jest trawersowany przez Enumerator i Iterator.
  7. Moduł wyliczający w Hashtablenie działa szybko.
  8. Hashtable dziedziczy klasę Dictionary.

Dalsza lektura Jaka jest różnica między HashMap i Hashtable w Javie?

wprowadź opis zdjęcia tutaj


Niemal ujęte w tej odpowiedzi (duplikat) - stackoverflow.com/a/39785829/432903 .
prayagupd

Dlaczego mówisz ~ „ Hashtable to starsza klasa ”? Gdzie jest na to dokumentacja uzupełniająca.
IgorGanapolsky

2
@IgorGanapolsky możesz to przeczytać - stackoverflow.com/questions/21086307/…
roottraveller

Utrzymanie HashMap jest kosztowne niż TreeMap. Ponieważ HashMap tworzy niepotrzebne dodatkowe wiadra.
Abdul

64

Oprócz tego, co powiedział izb, HashMapdopuszcza wartości zerowe, podczas gdy Hashtablenie.

Zauważ też, że Hashtablerozszerza Dictionaryklasę, która jako stan Javadocs jest przestarzała i została zastąpiona przez Mapinterfejs.


3
ale to nie czyni HashTable przestarzałym, prawda?
Pacerier

@Pacerier HashTable jest przestarzały od wersji Java 1.7.
Majid Ali Khan

62

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

Java Collection Matrix


49

Hashtablejest podobny do HashMapi ma podobny interfejs. Zaleca się korzystanie z niego HashMap, chyba że potrzebujesz obsługi starszych aplikacji lub synchronizacji, ponieważ Hashtablesmetody są zsynchronizowane. Więc w twoim przypadku, ponieważ nie jesteś wielowątkowy, HashMapsjesteś najlepszym wyborem.


36

Inną kluczową różnicą między hashtable i hashap jest to, że Iterator w HashMap jest szybki w razie awarii, podczas gdy moduł wyliczający dla Hashtable nie jest, i zgłasza ConcurrentModificationException, jeśli jakikolwiek inny wątek modyfikuje mapę strukturalnie przez dodanie lub usunięcie dowolnego elementu oprócz własnej metody remove (). Nie jest to jednak zachowanie gwarantowane i JVM dołoży wszelkich starań. ”

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


36

Oprócz wszystkich innych ważnych już wspomnianych tutaj aspektów, API API (np. Interfejs mapy) jest cały czas modyfikowane, aby było zgodne z „najnowszymi i największymi” dodatkami do specyfikacji Java.

Na przykład porównaj iterację mapy Java 5:

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

kontra stare podejście Hashtable:

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

W Javie 1.8 obiecujemy również, że będziemy mogli budować i uzyskiwać dostęp do HashMaps, jak w starych dobrych językach skryptowych:

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

Aktualizacja: Nie, nie wylądują w 1.8 ... :(

Czy ulepszenia kolekcji Project Coin będą dostępne w JDK8?


34

Hashtablejest zsynchronizowany, ale HashMapnie jest. To sprawia, że Hashtablewolniej niż Hashmap.

W przypadku aplikacji bez wątków używaj, HashMapponieważ pod względem funkcjonalności są one takie same.


30
  • HashTable jest zsynchronizowany, jeśli używasz go w jednym wątku, możesz użyć HashMap , który jest wersją niezsynchronizowaną. Niezsynchronizowane obiekty są często nieco bardziej wydajne. Nawiasem mówiąc, jeśli wiele wątków jednocześnie uzyskuje dostęp do HashMap i co najmniej jeden z wątków modyfikuje mapę strukturalnie, musi być zsynchronizowany zewnętrznie. Możesz owinąć niezsynchronizowaną mapę w zsynchronizowaną, używając:

    Map m = Collections.synchronizedMap(new HashMap(...));
  • HashTable może zawierać tylko niepuste obiekty jako klucz lub wartość. HashMap może zawierać jeden klucz zerowy i wartości zerowe.

  • Iteratory zwrócone przez Mapę działają szybko w razie awarii, jeśli mapa zostanie zmodyfikowana strukturalnie w dowolnym momencie po utworzeniu iteratora, w jakikolwiek sposób, z wyjątkiem własnej metody usuwania iteratora, iterator wyrzuci ConcurrentModificationException. Zatem w obliczu jednoczesnej modyfikacji iterator zawodzi szybko i czysto, zamiast ryzykować arbitralne, niedeterministyczne zachowanie w nieokreślonym czasie w przyszłości. Natomiast wyliczenia zwracane przez metody kluczy i elementów Hashtable nie są szybkie.

  • HashTable i HashMap są członkami Java Collections Framework (od platformy Java 2 v1.2, HashTable został zmodernizowany w celu implementacji interfejsu Map).

  • HashTable jest uważany za starszy kod, dokumentacja zaleca użycie ConcurrentHashMap zamiast Hashtable, jeśli pożądana jest bezpieczna dla wątków wysoce współbieżna implementacja.

  • HashMap nie gwarantuje kolejności zwracania elementów. W przypadku HashTable wydaje mi się, że jest tak samo, ale nie jestem do końca pewien, nie znajduję zasobu, który jasno to stwierdza.


30

HashMapi Hashtablemają również znaczne różnice algorytmiczne. Nikt wcześniej o tym nie wspominał, dlatego o tym wspominam. HashMapzbuduje tablicę skrótów o mocy dwóch rozmiarów, zwiększy ją dynamicznie tak, że masz maksymalnie osiem elementów (kolizji) w dowolnym segmencie i bardzo dobrze wymieszaj elementy dla ogólnych typów elementów. Jednak Hashtableimplementacja zapewnia lepszą i dokładniejszą kontrolę nad skrótem, jeśli wiesz, co robisz, a mianowicie możesz naprawić rozmiar tabeli, używając np. Najbliższej liczby pierwszej do rozmiaru domeny wartości, a to zapewni lepszą wydajność niż HashMap, tj. Mniej kolizji w niektórych przypadkach.

Niezależnie od oczywistych różnic omawianych obszernie w tym pytaniu, widzę Hashtable jako samochód „z napędem ręcznym”, w którym masz lepszą kontrolę nad haszowaniem, a HashMap jako odpowiednik „automatycznego napędu”, który ogólnie dobrze się spisuje.


27

W oparciu o informacje tutaj polecam korzystanie z HashMap. Myślę, że największą zaletą jest to, że Java uniemożliwi modyfikowanie go podczas iteracji, chyba że zrobisz to przez iterator.


5
W rzeczywistości nie zapobiega temu, po prostu go wykrywa i generuje błąd.
Bart van Heukelom,

1
Jestem prawie pewien, że wygeneruje wyjątek ConncurrentModificationException przed zmodyfikowaniem podstawowej kolekcji, chociaż mogę się mylić.
pkaeding

Podejmie próbę wykrycia równoczesnej modyfikacji i zgłasza wyjątek. Ale jeśli robisz coś z wątkami, nie może składać żadnych obietnic. Absolutnie wszystko może się zdarzyć, w tym złamanie .
cHao

24

A Collection- czasami nazywany kontenerem - to po prostu obiekt, który grupuje wiele elementów w jedną jednostkę. CollectionS są używane do przechowywania, pobierania, manipulowania i komunikowania danych agregowanych. Struktura kolekcji W to ujednolicona architektura do reprezentowania kolekcji i manipulowania nimi.

HashMap JDK1.2I HashTable JDK1.0zarówno stosuje się do oznaczania grup przedmiotów, które są reprezentowane w <Key, Value>pary. Każda <Key, Value>para nazywa się Entryobiektem. Zbiór wpisów jest określany przez obiekt HashMapi Hashtable. Klucze w kolekcji muszą być unikalne lub charakterystyczne. [ponieważ są używane do pobierania zamapowanej wartości określonego klucza. wartości w kolekcji można powielić.]


« Członek Superclass, Legacy and Collection Framework

Hashtable to wprowadzona w starszej klasie klasa JDK1.0, która jest podklasą klasy Dictionary. From JDK1.2Hashtable został przeprojektowany do implementacji interfejsu Map, aby stać się członkiem frameworka kolekcji. HashMap jest członkiem Java Collection Framework od samego początku jego wprowadzenia JDK1.2. HashMap jest podklasą klasy AbstractMap.

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 { ... }

« Początkowa wydajność i współczynnik obciążenia

Pojemność to liczba segmentów w tabeli skrótów, a początkowa pojemność to po prostu pojemność w momencie tworzenia tabeli skrótów. Zauważ, że tabela skrótów jest otwarta: w przypadku „ hashcollision” pojedyncze wiadro przechowuje wiele wpisów, które należy kolejno przeszukiwać. Współczynnik obciążenia jest miarą tego, jak pełne jest wypełnienie tabeli mieszającej, zanim jej pojemność zostanie automatycznie zwiększona.

HashMap tworzy pustą tablicę skrótów z domyślną początkową pojemnością (16) i domyślnym współczynnikiem obciążenia (0,75). Gdzie as Hashtable konstruuje pusty hashtable z domyślną pojemnością początkową (11) i współczynnikiem obciążenia / wypełnienia (0,75).

Mapa skrótów i tabela skrótów

« Modyfikacja strukturalna w przypadku zderzenia mieszającego

HashMap, Hashtablew przypadku kolizji skrótu przechowują wpisy map na połączonych listach. Z Java8,HashMap jeśli wiadro skrótu przekroczy określony próg, to wiadro się zmieni linked list of entries to a balanced tree. które poprawiają wydajność najgorszego przypadku od O (n) do O (log n). Podczas konwertowania listy na drzewo binarne kod skrótu jest używany jako zmienna rozgałęziająca. Jeśli w tym samym wiadrze znajdują się dwa różne kody skrótu, jeden jest uważany za większy i idzie na prawo od drzewa, a drugi na lewo. Ale gdy oba kody HashMapskrótu są równe, zakłada, że ​​klucze są porównywalne, i porównuje klucz w celu ustalenia kierunku, aby zachować pewną kolejność. Dobrą praktyką jest HashMap porównywanie kluczy . Po dodaniu wpisów, jeśli osiągnie rozmiar wiadraTREEIFY_THRESHOLD = 8przekonwertuj połączoną listę wpisów na zrównoważone drzewo, po usunięciu wpisów mniej niżTREEIFY_THRESHOLD i co najwyżej UNTREEIFY_THRESHOLD = 6przekształci zrównoważone drzewo w połączoną listę wpisów. Java 8 SRC , stosu

« Iteracja widoku kolekcji, Fast-Fast i Fail-Safe

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

Iteratorjest z natury szybki w działaniu. tzn. zgłasza ConcurrentModificationException, jeśli kolekcja jest modyfikowana podczas iteracji innej niż jej własna metoda remove (). Gdzie Enumerationz natury jest bezpieczny w razie awarii. Nie rzuca żadnych wyjątków, jeśli kolekcja jest modyfikowana podczas iteracji.

Zgodnie z dokumentacją Java API Docs, Iterator jest zawsze preferowany niż wyliczanie.

UWAGA: Funkcjonalność interfejsu wyliczania jest zduplikowana przez interfejs Iteratora. Ponadto Iterator dodaje opcjonalną operację usuwania i ma krótsze nazwy metod. Nowe implementacje powinny rozważyć użycie Iteratora zamiast opcji Wyliczanie.

W Javie 5 wprowadzono interfejs ConcurrentMap : ConcurrentHashMap- wysoce współbieżna, wysokowydajna ConcurrentMapimplementacja wspierana przez tablicę skrótów. Ta implementacja nigdy nie blokuje się podczas pobierania danych i pozwala klientowi wybrać poziom współbieżności dla aktualizacji. Ma on zastąpić drop-in dla Hashtable: oprócz implementacji ConcurrentMap, obsługuje wszystkie specyficzne dla niego „starsze” metody Hashtable.

  • Każda HashMapEntrywartość jest lotna, zapewniając w ten sposób drobną spójność ziarna dla spornych modyfikacji i kolejnych odczytów; każdy odczyt odzwierciedla najnowszą ukończoną aktualizację

  • Iteratory i wyliczenia są bezpieczne w razie awarii - odzwierciedlając stan w pewnym momencie od utworzenia iteratora / wyliczenia; pozwala to na jednoczesne odczyty i modyfikacje kosztem zmniejszonej spójności. Nie zgłaszają wyjątku ConcurrentModificationException. Jednak iteratory są zaprojektowane do użycia tylko przez jeden wątek na raz.

  • Podobnie, Hashtableale w przeciwieństwie do HashMaptej klasy, nie pozwala na użycie wartości null jako klucza lub wartości.

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();
    }
}

« Klucze zerowe i wartości zerowe

HashMapdopuszcza maksymalnie jeden klucz zerowy i dowolną liczbę wartości zerowych. Gdzie as Hashtablenie zezwala nawet na pojedynczy klucz zerowy i zerową wartość, jeśli klucz lub wartość zerowa jest, wówczas zgłasza wyjątek NullPointerException. Przykład

« Zsynchronizowany, bezpieczny dla wątków

Hashtablejest wewnętrznie zsynchronizowany. Dlatego bardzo bezpieczne jest stosowanie Hashtablew aplikacjach wielowątkowych. Gdzie HashMapnie jest wewnętrznie zsynchronizowany. Dlatego stosowanie HashMapw aplikacjach wielowątkowych bez zewnętrznej synchronizacji nie jest bezpieczne . Możesz zewnętrznie synchronizować HashMapza pomocą Collections.synchronizedMap()metody.

« Wydajność

Ponieważ Hashtablejest zsynchronizowany wewnętrznie, powoduje to, że jest Hashtablenieco wolniejszy niż HashMap.


@Widzieć


18

W przypadku aplikacji wielowątkowych często można uniknąć ConcurrentHashMap - w zależności od wymagań dotyczących wydajności.


17

1. Hashmaporaz HashTablezarówno klucz, jak i wartość.

2. Hashmapmoże przechowywać jeden klucz jako null. Hashtablenie można przechowywać null.

3. HashMapnie jest zsynchronizowany, ale Hashtablejest zsynchronizowany.

4. HashMapmoże być synchronizowany zCollection.SyncronizedMap(map)

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);

16

Oprócz wspomnianych różnic, należy zauważyć, że od Java 8 HashMapdynamicznie zastępuje Węzły (lista połączona) używane w każdym segmencie przez TreeNodes (czerwono-czarne drzewo), więc nawet jeśli występują kolizje o wysokim haszu, najgorszy przypadek, gdy wyszukiwanie jest

O (log (n)) dla HashMap Vs O (n) w Hashtable.

* Powyższa poprawa nie została zastosowana Hashtablejeszcze, ale tylko HashMap, LinkedHashMapi ConcurrentHashMap.

FYI, obecnie

  • TREEIFY_THRESHOLD = 8 : jeśli segment zawiera więcej niż 8 węzłów, połączona lista jest przekształcana w zrównoważone drzewo.
  • UNTREEIFY_THRESHOLD = 6 : gdy wiadro staje się zbyt małe (z powodu usunięcia lub zmiany rozmiaru), drzewo jest konwertowane z powrotem na listę połączoną.

14

Istnieje 5 podstawowych różnic w HashTable i HashMaps.

  1. Maps pozwala iterować i pobierać klucze, wartości oraz obie pary klucz-wartość, gdzie HashTable nie ma wszystkich tych możliwości.
  2. W Hashtable jest funkcja zawiera (), co jest bardzo mylące w użyciu. Ponieważ znaczenie zawiera jest nieco rozbieżne. Czy oznacza to, że zawiera klucz, czy zawiera wartość? trudne do zrozumienia. To samo w Mapach mamy funkcje ContainsKey () i ContainsValue (), które są bardzo łatwe do zrozumienia.
  3. W haszapie możesz bezpiecznie usuwać element podczas iteracji. gdzie nie jest to możliwe w tablicach skrótów.
  4. Tabele skrótów są domyślnie zsynchronizowane, dzięki czemu można łatwo używać wielu wątków. Gdzie jako HashMaps nie są domyślnie synchronizowane, więc można ich używać tylko z jednym wątkiem. Ale nadal możesz przekonwertować HashMap na zsynchronizowany za pomocą funkcji SynchronMM klasy Maps (Map m) w kolekcji.
  5. HashTable nie zezwala na klucze zerowe lub wartości zerowe. Gdzie jako HashMap pozwala na jeden klucz zerowy i wiele wartości zerowych.

13

Mój mały wkład:

  1. Pierwsza i najbardziej znacząca różnica pomiędzy Hashtablei HashMapjest taka, że HashMapnie jest bezpieczna Hashtabledla wątków, podczas gdy jest dla kolekcji bezpiecznych dla wątków.

  2. Drugą ważną różnicą między Hashtablei HashMapjest wydajność, ponieważ HashMapnie jest zsynchronizowana, działa lepiej niż Hashtable.

  3. Trzecią różnicą w Hashtableporównaniu z vs HashMapjest to, że Hashtablejest to przestarzała klasa i powinieneś jej używać ConcurrentHashMapzamiast Hashtablew Javie.


11

HashMap: jest to klasa dostępna w pakiecie java.util i służy do przechowywania elementu w formacie klucza i wartości.

Hashtable: Jest to klasyczna klasa, która jest rozpoznawana w ramach kolekcji.


Jeśli tak, to powinno być w komentarzach, a nie jako odpowiedź.
manikant gautam

10

HashTable to starsza klasa w jdk, której nie należy już używać. Zamień jego użycie na ConcurrentHashMap . Jeśli nie potrzebujesz bezpieczeństwa wątków, użyj HashMap, który nie jest wątkowo bezpieczny, ale szybszy i zużywa mniej pamięci.


Ponieważ myślałem, że inne odpowiedzi w tamtym czasie nie odrzuciły HashTable, ale wyjaśniły, że to jest bezpieczne dla wątków. Prawda jest taka, że ​​jak tylko zobaczysz HashTable w kodzie, powinieneś zastąpić go ConcurrentHashMap bez pomijania rytmu. A jeśli bezpieczeństwo wątków nie stanowi problemu, można użyć HashMap, aby nieco poprawić wydajność.
jontejj

10
  1. Hashtablejest zsynchronizowany, podczas gdy HashMapnie jest.
  2. Inną różnicą jest to, że iterator w HashMapjest bezpieczny w razie awarii, podczas gdy moduł wyliczający dla Hashtablenie. Jeśli zmienisz mapę podczas iteracji, będziesz wiedział.
  3. HashMapdopuszcza w nim wartości zerowe, podczas gdy Hashtablenie.

3
Iterator HashMap działa szybko i niezawodnie. Właśnie dlatego mamy ConcurrentHashMap, która umożliwia modyfikację podczas iteracji. Sprawdź ten post journaldev.com/122/…
Pankaj

9

HashMap i HashTable

  • Kilka ważnych punktów na temat HashMap i HashTable. proszę przeczytać poniższe szczegóły.

1) Hashtable i Hashmap implementują interfejs java.util.Map 2) Zarówno Hashmap, jak i Hashtable to kolekcja oparta na haszowaniu. i praca nad haszowaniem. więc są to podobieństwa między HashMap i HashTable.

  • Jaka jest różnica między HashMap a HashTable?

1) Pierwszą różnicą jest to, że HashMap nie jest bezpieczny dla wątków, podczas gdy HashTable jest ThreadSafe
2) HashMap jest lepszy pod względem wydajności, ponieważ nie jest bezpieczny dla wątków. natomiast wydajność Hashtable nie jest lepsza, ponieważ jest bezpieczna dla wątków. więc wiele wątków nie może jednocześnie uzyskać dostępu do Hashtable.


2
Unieważniono, ponieważ w niektórych aspektach ta odpowiedź jest nieprawidłowa. Hashtable nie implementuje interfejsu Map, ale jedynie rozszerza klasę Dictionary, która jest przestarzała.
Yannis Sermetziadis

8

Hashtable:

Hashtable to struktura danych, która zachowuje wartości pary klucz-wartość. Nie dopuszcza wartości null zarówno dla kluczy, jak i wartości. Otrzymasz, NullPointerExceptionjeśli dodasz wartość zerową. Jest zsynchronizowany. Więc pochodzi z jego kosztów. Tylko jeden wątek może uzyskać dostęp do HashTable w określonym czasie.

Przykład :

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 jest jak Hashtable, ale akceptuje także parę wartości klucza. Pozwala zerować zarówno klucze, jak i wartości. Jego wydajność jest lepsza niż HashTable, ponieważ jest unsynchronized.

Przykład:

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));

    }
}

5

HashMapjest emulowany, a zatem można go używać, GWT client codea Hashtablenie jest.


Czy to wyczerpujący opis różnic między dwoma apis?
IgorGanapolsky

Tak (sic!). To wszystko, co programiści GWT muszą o tym wiedzieć.
pong

5

Stary i klasyczny temat, po prostu chcę dodać ten pomocny blog, który wyjaśnia to:

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

Blog Manisha Chhabry

5 głównych różnic między HashMap i Hashtable

Zarówno HashMap, jak i Hashtable implementują interfejs java.util.Map, ale istnieją pewne różnice, które programiści Java muszą zrozumieć, aby napisać bardziej wydajny kod. Począwszy od platformy Java 2 v1.2 klasa Hashtable została zmodernizowana w celu zaimplementowania interfejsu Map, co czyni ją członkiem środowiska Java Collections Framework.

  1. Jedną z głównych różnic między HashMap i Hashtable jest to, że HashMap nie jest zsynchronizowany, podczas gdy Hashtable jest zsynchronizowany, co oznacza, że ​​Hashtable jest bezpieczny dla wątków i może być współdzielony między wieloma wątkami, ale HashMap nie może być dzielony między wieloma wątkami bez odpowiedniej synchronizacji. Java 5 wprowadziła ConcurrentHashMap, która jest alternatywą dla Hashtable i zapewnia lepszą skalowalność niż Hashtable w Javie. Zsynchronizowane oznacza, że ​​tylko jeden wątek może modyfikować tablicę skrótów w jednym momencie. Zasadniczo oznacza to, że każdy wątek przed wykonaniem aktualizacji tablicy mieszającej będzie musiał uzyskać blokadę obiektu, podczas gdy inni będą czekać na zwolnienie blokady.

  2. Klasa HashMap jest z grubsza odpowiednikiem Hashtable, z tym wyjątkiem, że dopuszcza wartości null. (HashMap zezwala na wartości null jako klucz i wartość, podczas gdy Hashtable nie zezwala na wartości null).

  3. Trzecią znaczącą różnicą między HashMap a Hashtable jest to, że Iterator w HashMap jest iteratorem, który szybko działa w trybie awaryjnym, podczas gdy moduł wyliczający dla Hashtable nie jest i zgłasza ConcurrentModificationException, jeśli jakikolwiek inny wątek modyfikuje mapę strukturalnie przez dodanie lub usunięcie dowolnego elementu z wyjątkiem własnego usunięcia Iteratora ( ) metoda. Nie jest to jednak zachowanie gwarantowane i JVM dołoży wszelkich starań. Jest to również ważna różnica między wyliczaniem a Iteratorem w Javie.

  4. Jeszcze jedną zauważalną różnicą między Hashtable i HashMap jest to, że ze względu na bezpieczeństwo wątków i synchronizację Hashtable jest znacznie wolniejszy niż HashMap, jeśli jest używany w środowisku jednowątkowym. Jeśli więc nie potrzebujesz synchronizacji, a HashMap jest używany tylko przez jeden wątek, wykonaj Hashtable w Javie.

  5. HashMap nie gwarantuje, że kolejność mapy pozostanie stała w czasie.

Pamiętaj, że HashMap może być synchronizowany przez

Map m = Collections.synchronizedMap(hashMap);

Podsumowując, istnieją znaczne różnice między Hashtable i HashMap w Javie, np. Bezpieczeństwo wątków i szybkość, i na tej podstawie używaj Hashtable tylko wtedy, gdy absolutnie potrzebujesz bezpieczeństwa wątków, jeśli używasz Java 5, rozważ użycie ConcurrentHashMap w Javie.


ConcurrentHashMap nie jest zsynchronizowany z odczytem, ​​podczas gdy Hashtable jest. Jeśli więc masz wiele operacji odczytu wykonywanych jednocześnie z zapisem, Hashtable będzie ci lepiej służył, jeśli zależy Ci na integralności danych.
IgorGanapolsky

5

Zarówno HashMap, jak i Hashtable służą do przechowywania danych w formie klucza i wartości. Oba używają techniki mieszania do przechowywania unikalnych kluczy. Istnieje wiele różnic między klasami HashMap i Hashtable, które podano poniżej.

wprowadź opis zdjęcia tutaj


Ładne streszczenie wizualne!
Nadjib Mami
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.