Відмінності між HashMap і Hashtable?


3749

Які відмінності між a HashMapі a Hashtableу Java?

Що є більш ефективним для безпотокових програм?


17
HashTable застарілий у Java 1.7, і рекомендується використовувати впровадження ConcurrentMap
MissFiona

@MissFiona Ні, ConcurrentMapце не потрібно, оскільки в запитанні йдеться про "додатки без потоків", що означають, що нитка / паралельність не є проблемою.
Василь Бурк

Відповіді:


3773

Існує кілька відмінностей між HashMapта Hashtableна Java:

  1. Hashtableбуде синхронізовано , тоді як це HashMapне так. Це робить HashMapдля додатків без потоків рівномірніші, оскільки несинхронізовані об'єкти зазвичай працюють краще, ніж синхронізовані.

  2. Hashtableне дозволяє nullключі або значення. HashMapдозволяє один nullключ і будь-яку кількість nullзначень.

  3. Один з підкласів HashMap є LinkedHashMap, таким чином , в тому випадку, якщо ви хочете передбачуваний порядок ітерації (що порядок вставки за замовчуванням), ви можете легко поміняти HashMapдля LinkedHashMap. Це не було б так просто, якби ви користувались Hashtable.

Оскільки синхронізація не є проблемою для вас, я б рекомендував HashMap. Якщо синхронізація стає проблемою, ви також можете подивитися ConcurrentHashMap.


84
Якщо ви хочете зробити безпечний потік для HashMap, використовуйте Collections.synchronizedMap().
Рок Стрішні

275
Я також зауважу, що наївний підхід до безпеки потоку Hashtable("синхронізація кожного методу повинен вирішувати будь-які проблеми з одночасністю!") Робить це дуже гіршим для потокових програм. Вам краще зовнішньо синхронізувати HashMap(і думати про наслідки) або скористатися ConcurrentMapреалізацією (та використовувати розширений API для одночасності). Підсумок: єдиною причиною для використання Hashtableє те, коли потрібний застарілий API (приблизно з 1996 р.).
еріксон

8
HashMap надає гнучкості програмісту для написання коду threadSafe, коли він фактично ним користується. Рідко траплялося, що мені потрібна безпечна колекція потоків, як ConcurrentHashMap або HashTable. Мені потрібно було певний набір функцій або певні заяви у синхронізованому блоці, щоб бути безпечними для потоків.
Гаурава Агарвал

2
Hashtable застарілий, і ми використовуємо HashMap для безпечного середовища, що не стосується потоків. Якщо вам потрібна безпека потоку, то ви можете використовувати Collections.synchronizedMap () або використовувати ConcurrentHashMap, який є більш ефективним та хеш-файлом.
Манеєш Кумар

1
Це застаріле, але не застаріле, і мені цікаво, чому це так. Я здогадуюсь, що видалення цього класу (і Vector з тих же причин) порушить занадто багато існуючого коду, а примітка за допомогою @Deprecated означатиме намір видалити код, якого, мабуть, немає.
Джиллес ван Гурп

682

Зауважте, що багато відповідей стверджують, що Hashtable синхронізовано. На практиці це купує вам дуже мало. Синхронізація методами accessor / mutator зупинить два потоки додавання або видалення з карти одночасно, але в реальному світі вам часто потрібна додаткова синхронізація.

Дуже поширена ідіома - "перевірити, а потім поставити" - тобто шукати запис у Map, і додавати його, якщо його ще немає. Це жодним чином не є атомною операцією, використовуєте ви Hashtableчи HashMap.

Еквівалентно синхронізований HashMapможе бути отриманий:

Collections.synchronizedMap(myMap);

Але для правильної реалізації цієї логіки потрібна додаткова синхронізація форми:

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

Навіть ітерація над Hashtableзаписами 's (або HashMapотримана за допомогою Collections.synchronizedMap) не є безпечною для потоків, якщо ви також не захистите їх Mapвід модифікації шляхом додаткової синхронізації.

Реалізації ConcurrentMapінтерфейсу (наприклад ConcurrentHashMap) вирішують щось із цього, включаючи безпечну потокову семантику check-then-act, наприклад:

ConcurrentMap.putIfAbsent(key, value);

53
Також зауважте, що якщо HashMap модифікований, ітератори, що вказують на нього, стають недійсними.
Кріс К

3
То чи є різниця між синхронізованими (myMap) {...} та ConcurrentHashMap з точки зору безпечності потоку?
telebog

3
Дуже правда, я намагався пояснити те саме тут .. lovehasija.com/2012/08/16/…
Love Hasija

@Bhushan: Це буде кидатись з найкращих зусиль, це не гарантована поведінка: docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
Метт Стівенсон

Перебуваючи в середині екіпажу з розвитку JVM протягом декількох років, я можу констатувати, що внутрішня синхронізація Hashtable є принаймні корисною для правильного вказівки пальцем на код замовника, коли він пише хиткий одночасний код. Ми отримали кілька скарг на збої всередині HashMap (і, отже, "очевидно" помилка JDK / JVM), коли причиною були одночасні зміни.
Гарячий лизає

363

Hashtableвважається застарілим кодом. Нічого про Hashtableце не можна зробити з використанням HashMapабо виведенням HashMap, тому для нового коду я не бачу жодного виправдання для повернення до Hashtable.


101
З Hashtable javadoc (наголос додано): "Станом на платформу Java 2 v1.2, цей клас був модернізований для реалізації інтерфейсу Map, завдяки чому він став членом Java Collections Framework ". Однак ви праві, що це застарілий код. Усі переваги синхронізації можна отримати ефективніше за допомогою Collections.synchronizedMap (HashMap). (Подібно до вектора як застарілої версії Collections.synchronizedList (ArrayList).)
Kip

15
@ aberrant80: на жаль, у вас немає вибору між двома і вам доведеться використовувати Hashtable при програмуванні для J2ME ...
pwes

6
цю відповідь слід видалити. він містить невірну інформацію та має багато оновлень.
anon58192932

@ anon58192932 Чи можна відредагувати питання, щоб його виправити?
GC_

1
Ми маємо привернути увагу плаката @ aberrant80 або адміністратора шляхом позначення. Позначення може допомогти - спробуй це зараз.
anon58192932

189

Це питання часто задають в інтерв'ю, щоб перевірити, чи розуміє кандидат правильне використання класів колекції та чи знає альтернативні варіанти.

  1. HashMapКлас приблизно відповідає Hashtable, за винятком того, що вона не синхронізована і дозволяють нулі. ( HashMapдозволяє нульові значення як ключ і значення, тоді як Hashtableне дозволяє nulls).
  2. HashMap не гарантує, що порядок карти залишатиметься незмінним у часі.
  3. HashMapне синхронізований, тоді Hashtableяк синхронізований.
  4. Ітератор у програмі HashMapвиходить з ладу, тоді як нумератор Hashtableне є і кидає, ConcurrentModificationExceptionякщо будь-який інший потік структурно змінює карту, додаючи або видаляючи будь-який елемент, крім Iteratorвласного remove() методу. Але це не є гарантованою поведінкою, і СП буде виконувати все можливе.

Примітка про деякі важливі умови:

  1. Синхронізований засіб лише один потік може змінювати хеш-таблицю в один момент часу. В основному це означає, що будь-який потік перед виконанням оновлення на замовленні Hashtableповинен буде придбати замок на об'єкті, тоді як інші чекатимуть звільнення блокування.
  2. Наявність відмови від безпеки є актуальною в контексті ітераторів. Якщо ітератор був створений для об'єкта колекції, а інший потік намагається модифікувати об'єкт колекції "структурно", буде викинуто виняток паралельної модифікації. Можливо, для інших потоків можна посилатися на setметод, оскільки він не модифікує колекцію "структурно". Однак, якщо до виклику setколекцію структурно модифікували, IllegalArgumentExceptionвона буде кинута.
  3. Структурно модифікація означає видалення або вставлення елемента, який міг би ефективно змінити структуру карти.

HashMap може бути синхронізовано

Map m = Collections.synchronizeMap(hashMap);

Карта забезпечує перегляди колекції замість прямої підтримки ітерації через об'єкти перерахування. Перегляди колекції значно підвищують виразність інтерфейсу, про що йдеться далі в цьому розділі. Карта дозволяє переглядати ключі, значення або пари ключів і значень; Hashtableне передбачає третього варіанту. Карта забезпечує безпечний спосіб видалення записів у розпал ітерації; Hashtableне. Нарешті, Map виправляє незначний недолік в Hashtableінтерфейсі. Hashtableмає метод, який називається містить, який повертає істину, якщо Hashtableмістить задане значення. З огляду на його ім'я, можна було очікувати , цей метод повертає істину , якщо Hashtableмістить заданий ключ, оскільки ключ є основним механізмом доступу для Hashtable. Інтерфейс Map усуває це джерело плутанини шляхом перейменування методу containsValue. Також це покращує послідовність інтерфейсу - containsValueпаралелі containsKey.

Інтерфейс карти


19
Ця відповідь містить щонайменше дві суттєві фактичні неточності. Це, звичайно, НЕ заслуговує на це багато нагород.
Стівен C

58
1) Ітератори HashMap НЕ захищені від збоїв. Вони виходять з ладу. Існує величезна різниця в значенні між цими двома термінами. 2) Немає setоперації на a HashMap. 3) put(...)Операція не кинеться, IllegalArgumentExceptionякщо відбулася попередня зміна. 4) Невдала поведінка системи HashMap також виникає, якщо змінити відображення. 5) Нерабочий-швидко поведінку буде гарантовано. (Що не гарантується, це поведінка, HashTableякщо ви робите одночасну модифікацію. Фактична поведінка ... непередбачувана.)
Stephen C

25
6) Hashtableне гарантує, що порядок елементів карти також буде стабільним у часі. (Ви , можливо , плутаючи Hashtableз LinkedHashMap.)
Стівен C

4
Хтось ще насправді хвилюється, що студенти сьогодні отримують помилкову думку про те, що отримання "синхронізованих версій" колекцій якимось чином означає, що вам не доведеться зовнішньо синхронізувати складні операції? Мій улюблений приклад цього буття, thing.set(thing.get() + 1);яке частіше за все ловить новачків зненацька, як абсолютно незахищений, особливо якщо це get()і set()є синхронізованими методами. Багато з них очікують магії.

Ітератори на HashMap не є безпечними
Абдул

130

HashMap: Реалізація Mapінтерфейсу, який використовує хеш-коди для індексації масиву. Hashtable: Привіт, 1998 р. Зателефонував. Вони хочуть повернути API своїх колекцій.

Якщо серйозно, то вам краще Hashtableвзагалі не триматися подалі . Для однопотокових програм вам не потрібні додаткові накладні витрати на синхронізацію. Для програм, що ведуть одночасне використання, параноїдальна синхронізація може призвести до голоду, тупиків або непотрібних пауз з вивезенням сміття. Як зазначив Тім Хоуланд, ви можете використовувати це ConcurrentHashMapзамість цього.


Це насправді має сенс. ConcurrentHashMaps дає свободу синхронізації, а налагодження набагато простіше.
prap19

1
Це специфічно для Java чи всієї реалізації хеш-карти.

125

Майте на увазі, що це HashTableбуло старим класом до впровадження Java Collections Framework (JCF) і пізніше було оновлено для реалізації Mapінтерфейсу. Так було Vectorі Stack.

Тому завжди тримайтеся подалі від них у новому коді, оскільки в JCF завжди є краща альтернатива, як вказували інші.

Ось чіт-лист колекції Java, який ви знайдете корисним. Зауважте, сірий блок містить застарілий клас HashTable, Vector та Stack.

введіть тут опис зображення


72

Тут вже багато хороших відповідей. Я додаю кілька нових пунктів і резюмую.

HashMapі Hashtableобидва використовуються для зберігання даних у формі ключа та значення . Обидва використовують техніку хешування для зберігання унікальних ключів. Але існує багато відмінностей між класами HashMap і Hashtable, які наведені нижче.

HashMap

  1. HashMapне синхронізовано. Він не є безпечним для потоків і не може ділитися між багатьма потоками без належного коду синхронізації.
  2. HashMap дозволяє один нульовий ключ і кілька нульових значень.
  3. HashMap це новий клас, представлений в JDK 1.2.
  4. HashMap швидко.
  5. Ми можемо зробити HashMapяк синхронізований, викликаючи цей код
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap проходить Ітератор.
  7. Ітератор у програмі HashMapне працює.
  8. HashMap успадковує клас AbstractMap.

Хешбел

  1. Hashtableсинхронізовано. Він безпечний для потоків і може бути спільним для багатьох потоків.
  2. Hashtable не допускає жодного нульового ключа або значення.
  3. Hashtable це клас спадщини.
  4. Hashtable повільно.
  5. Hashtable внутрішньо синхронізований і не може бути синхронізований.
  6. Hashtable проходить шляхом перечислювача та ітератора.
  7. Нумератор Hashtableне є швидким.
  8. Hashtable успадковує клас словника.

Подальше читання Яка різниця між HashMap та Hashtable у Java?

введіть тут опис зображення


Досить висвітлено у цій відповіді (дублікат) - stackoverflow.com/a/39785829/432903 .
prayagupd

Чому ви кажете ~ " Хештел - це спадщина клас "? Де знаходиться супровідна документація на це.
ІгорГанапольський

2
@IgorGanapolsky ви можете прочитати це - stackoverflow.com/questions/21086307 / ...
roottraveller

Підтримка HashMap затратна, ніж TreeMap. Тому що HashMap створює непотрібні зайві відра.
Абдул

64

Окрім того, що izb сказав, HashMapдопускає нульові значення, тоді як значення Hashtableцього немає.

Також зауважте, що Hashtableрозширення Dictionaryкласу, який як стан Javadocs , є застарілим і його замінив Mapінтерфейс.


3
але це не робить HashTable застарілим?
Pacerier

@Pacerier HashTable застарілий з Java 1.7.
Маджід Алі Хан

62

Погляньте на цю діаграму. Він забезпечує порівняння між різними структурами даних разом із HashMapта Hashtable. Порівняння точне, чітке і легко зрозуміле.

Матриця колекції Java


49

Hashtableподібний до HashMapта має аналогічний інтерфейс. Рекомендується використовувати HashMap, якщо вам не потрібна підтримка застарілих програм або вам потрібна синхронізація, оскільки Hashtablesметоди синхронізовані. Тож у вашому випадку, оскільки ви не багатопоточні, HashMapsнайкраща ставка.


36

Ще одна ключова відмінність хешбюля від хешмапу полягає в тому, що Iterator в HashMap є невдалим, тоді як нумератор для Hashtable не є і кидає ConcurrentModificationException, якщо будь-який інший Thread змінює карту структурно, додаючи або видаляючи будь-який елемент, крім власного методу delete () Iterator. Але це не є гарантованою поведінкою, і СП буде виконувати все можливе ".

Моє джерело: http://javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html


36

Окрім усіх інших важливих аспектів, про які вже говорилося тут, API колекцій (наприклад, інтерфейс карти) постійно змінюється, щоб відповідати "останнім і найбільшим" доповненням до специфікації Java.

Наприклад, порівняйте ітерацію карти Java 5:

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

проти старого підходу Hashtable:

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

У Java 1.8 нам також обіцяють створити та отримати доступ до HashMaps, як у старих хороших мовах сценаріїв:

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

Оновлення: Ні, вони не приземляться через 1.8 ... :(

Чи будуть розширення колекції Project Coin в JDK8?


34

Hashtableсинхронізовано, тоді HashMapяк ні. Це робить Hashtableповільніше, ніж Hashmap.

Для програм без потоків використовуйте, HashMapоскільки вони інакше однакові за функціональністю.


30
  • HashTable синхронізований, якщо ви використовуєте його в одному потоці, ви можете використовувати HashMap , який є несинхронізованою версією. Несинхронізовані об'єкти часто трохи ефективніші. До речі, якщо кілька потоків отримують доступ до HashMap одночасно, і принаймні один з потоків структурно модифікує карту, вона повинна бути синхронізована зовні. Неможливо синхронізувати карту в синхронізовану за допомогою:

    Map m = Collections.synchronizedMap(new HashMap(...));
  • HashTable може містити лише ненульовий об'єкт як ключ або як значення. HashMap може містити один нульовий ключ і нульові значення.

  • Ітератори, повернені Map, невдалі, якщо карта структурно модифікована в будь-який час після створення ітератора, будь-яким способом, за винятком власного методу видалення ітератора, ітератор видалить ConcurrentModificationException. Таким чином, в умовах одночасних модифікацій ітератор виходить з ладу швидко і чисто, замість того, щоб ризикувати довільною недетермінованою поведінкою у невизначений час у майбутньому. Тоді як перерахування, повернені ключами та методами елементів Hashtable, не є швидкими.

  • HashTable і HashMap є членами Java Collections Framework (оскільки платформа Java 2 v1.2, HashTable була дооснащена для реалізації інтерфейсу Map).

  • HashTable вважається застарілим кодом, документація радить використовувати ConcurrentHashMap замість Hashtable, якщо потрібна безпечна для потоків реалізація.

  • HashMap не гарантує порядок повернення елементів. Для HashTable я думаю, що це те саме, але я не зовсім впевнений, я не знаходжу ресурс, який би це чітко зазначив.


30

HashMapі Hashtableмають значні алгоритмічні відмінності. Ніхто раніше не згадував про це, тому я і виховую це. HashMapпобудує хеш-таблицю потужністю в два розміри, динамічно збільшить її, щоб у вас було щонайменше близько восьми елементів (зіткнень) у будь-якому відрі і дуже добре перемішав би елементи для загальних типів елементів. Однак Hashtableреалізація забезпечує кращий і точніший контроль над хешированием, якщо ви знаєте, що ви робите, а саме ви можете виправити розмір таблиці, використовуючи, наприклад, найближчий простий номер до вашого розміру домену значень, і це призведе до кращої продуктивності, ніж HashMap, тобто менше зіткнень для деяких випадків.

Окремо від очевидних розбіжностей, обговорених широко в цьому питанні, я бачу Hashtable як автомобіль з "ручним приводом", де ви краще контролюєте хеширование та HashMap як аналог "автоматичного приводу", який, як правило, справляється добре.


27

Виходячи з інформації тут , я рекомендую перейти з HashMap. Я думаю, що найбільша перевага полягає в тому, що Java заважатиме вам змінювати її під час ітерації над нею, якщо ви не зробите це через ітератор.


5
Насправді це не заважає, він просто виявляє і видає помилку.
Барт ван Хекелом

1
Я майже впевнений, що він викине ConncurrentModificationException до зміни базової колекції, хоча я можу помилитися.
pkaeding

Він спробує виявити одночасну модифікацію та викине виняток. Але якщо ви щось робите з нитками, це не може обіцяти. Може статися абсолютно все, включаючи поломку .
cHao

24

А Collection- іноді називається контейнером - це просто об'єкт, який групує кілька елементів в одну одиницю. Collections використовуються для зберігання, пошуку, маніпулювання та передачі сукупних даних. Рамка колекцій W - це єдина архітектура для представлення та маніпулювання колекціями.

HashMap JDK1.2І Hashtable JDK1.0, і використовується для представлення групи об'єктів, які представлені в <Key, Value>парі. Кожна <Key, Value>пара називається Entryоб'єктом. Збірник записів посилається на об'єкт HashMapі Hashtable. Ключі в колекції повинні бути унікальними або відмінними. [як вони використовуються для отримання відображеного значення певного ключа. значення в колекції можна дублювати.]


« Член Рамкового рівня, Спадщини та Колекції

Hashtable - це введений у спадщину клас JDK1.0, який є підкласом класу Словник. Від JDK1.2Hashtable реінжинірований для реалізації інтерфейсу Map, щоб зробити членом колекції рамки. HashMap є членом Java Collection Framework з самого початку її впровадження в JDK1.2. HashMap - це підклас класу 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 { ... }

« Початкова потужність і коефіцієнт навантаження

Ємність - це кількість відро в хеш-таблиці, а початкова ємність - просто ємність у момент створення хеш-таблиці. Зауважте, що хеш-таблиця відкрита: у випадку " hashcollision" одного відра зберігає кілька записів, які необхідно шукати послідовно. Коефіцієнт навантаження - це міра того, наскільки дозволено отримати хеш-таблицю до автоматичного збільшення її ємності.

HashMap створює порожню хеш-таблицю з початковою ємністю за замовчуванням (16) та коефіцієнтом навантаження за замовчуванням (0,75). Де, як Hashtable будує порожній хешбел із початковою ємністю за замовчуванням (11) та коефіцієнтом завантаження / коефіцієнтом заповнення (0,75).

Карта та хеш-хеш

« Структурна модифікація на випадок зіткнення хешу

HashMap, Hashtableу випадку зіткнення хешу вони зберігають записи карти у пов'язаних списках. З Java8,HashMap якщо хеш-відро зростає за певний поріг, з цього відра вимкнетьсяlinked list of entries to a balanced tree . які покращують найгірші показники від O (n) до O (log n). Під час перетворення списку у двійкове дерево, хеш-код використовується як змінна гілка. Якщо в одному відрі є два різних хеш-коди, один вважається більшим і йде праворуч від дерева, а інший - зліва. Але коли обидва хеш-коди рівні, HashMapпередбачається, що ключі порівнянні, і порівнює ключ для визначення напрямку, щоб можна було підтримувати певний порядок. Це хороша практика зробити ключі HashMap порівнянними . Додавання записів, якщо розмір відра досягаєTREEIFY_THRESHOLD = 8перетворити зв'язаний список записів у збалансоване дерево, при видаленні записів менше TREEIFY_THRESHOLD і щонайменше UNTREEIFY_THRESHOLD = 6поверне збалансоване дерево у пов'язаний список записів. Java 8 SRC , стекпост

« Ітерація перегляду колекції, Fail-Fast і Fail-Safe

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

Iteratorє невдалим характером. тобто він кидає ConcurrentModificationException, якщо колекцію модифікують під час ітерації, відмінного від власного методу delete (). Там, де Enumerationце безпечно відмови. Він не кидає жодних винятків, якщо колекція модифікується під час ітерації.

Згідно з Java API Docs, Iterator завжди перевага перед перерахуванням.

ПРИМІТКА . Функціонал інтерфейсу перерахування дублюється інтерфейсом Iterator. Крім того, Iterator додає необов'язкову операцію видалення та має більш короткі назви методів. Новим реалізаціям слід розглянути можливість використання Iterator у перевазі «Перерахування».

В Java 5 представлений ConcurrentMap Interface : ConcurrentHashMap- високо одночасне, високоефективне ConcurrentMapреалізація, підкріплене хеш-таблицею. Ця реалізація ніколи не блокується під час пошуку і дозволяє клієнту вибрати рівень одночасності оновлень. Він призначений як заміна заміни для Hashtable: окрім впровадження ConcurrentMap, він підтримує всі властивості "спадщини" Hashtable.

  • Кожне HashMapEntryзначення s є непостійним, завдяки чому забезпечується тонкодисперсна зернистість для заявлених модифікацій та наступних зчитувань; кожне прочитане відображає останнє завершене оновлення

  • Ітератори та перерахування є безпечними для відмов - відображають стан у певний момент з моменту створення ітератора / перерахування; це дозволяє одночасно читати та модифікувати ціною зниженої послідовності. Вони не кидають ConcurrentModificationException. Однак ітератори призначені для використання лише однією ниткою за один раз.

  • Як Hashtableі на відміну від HashMapцього, цей клас не дозволяє використовувати null як ключ або значення.

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

« Нульові ключі та нульові значення

HashMapдозволяє максимально один нульовий ключ і будь-яку кількість нульових значень. Де як Hashtableне дозволяє навіть один нульовий ключ і нульове значення, якщо ключ або значення null, то він кидає NullPointerException. Приклад

« Синхронізована, безпечна для потоків

Hashtableвнутрішньо синхронізований. Тому використовувати його Hashtableв багатопотокових програмах дуже безпечно . Де як HashMapвнутрішньо не синхронізовано. Тому використання HashMapв багатопотокових програмах без зовнішньої синхронізації не є безпечним . Ви можете зовнішньо синхронізувати HashMapза допомогою Collections.synchronizedMap()методу.

« Виступ

Як Hashtableце внутрішньо синхронізовано, це робить Hashtableтрохи повільніше, ніж HashMap.


@Подивитися


18

Для потокових програм ви можете часто піти з ConcurrentHashMap - це залежить від ваших вимог щодо продуктивності.


17

1. Hashmapі HashTableключ зберігання, і значення.

2. Hashmapможе зберігати один ключ як null. Hashtableне можна зберігати null.

3. HashMapне синхронізований, але Hashtableсинхронізований.

4. HashMapможуть бути синхронізовані зCollection.SyncronizedMap(map)

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);

16

Крім відмінностей, про які вже згадувалося, слід зазначити, що оскільки Java 8 HashMapдинамічно замінює Вузли (зв'язаний список), що використовуються у кожному відрі, TreeNodes (червоно-чорне дерево), так що навіть при великих зіткненнях хешу, найгірший випадок, коли пошук є

O (log (n)) для HashMap Vs O (n) в Hashtable.

* Вищезазначене поліпшення не застосовується до Hashtableще, але тільки HashMap, LinkedHashMapі ConcurrentHashMap.

На даний момент,

  • TREEIFY_THRESHOLD = 8 : якщо відро містить більше 8 вузлів, пов'язаний список перетворюється на збалансоване дерево.
  • UNTREEIFY_THRESHOLD = 6 : коли відро стає занадто малим (через видалення чи зміну розміру) дерево перетворюється назад у пов'язаний список.

14

Існує 5 основних диференціацій з HashTable і HashMaps.

  1. Карти дозволяють повторювати та вибирати ключі, значення та обидві пари ключ-значення, де HashTable не має всієї цієї можливості.
  2. У Hashtable є функція містить (), що дуже заплутано у використанні. Тому що значення вмісту трохи відхиляється. Чи означає це, що містить ключ чи містить значення? важко зрозуміти. Те саме в Maps є функціями ContainsKey () та ContainsValue (), які легко зрозуміти.
  3. У хешмапі можна безпечно видаляти елемент під час ітерації. де це неможливо в хештелях.
  4. За замовчуванням HashTables синхронізується, тому його можна легко використовувати з декількома потоками. Якщо HashMaps не синхронізовані за замовчуванням, то їх можна використовувати лише з одним потоком. Але ви все одно можете перетворити HashMap в синхронізований за допомогою функції синхронізованої карти (Collection m) колекції util.
  5. HashTable не дозволятиме нульових ключів або нульових значень. Де, як HashMap, дозволяє один нульовий ключ і кілька нульових значень.

13

Мій невеликий внесок:

  1. Перше і найзначніше розрізнялися Hashtableі в HashMapтому , що, HashMapНЕ поточно-то час Hashtableє поточно-колекція.

  2. Друга важлива відмінність між Hashtableі HashMap- це продуктивність, оскільки HashMapне синхронізована, вона працює краще, ніж Hashtable.

  3. Третя відмінність від Hashtablevs HashMapполягає в тому, що Hashtableце застарілий клас, і його слід використовувати ConcurrentHashMapзамість HashtableJava.


11

HashMap: Це клас, доступний у пакеті java.util, і він використовується для зберігання елемента у форматі ключа та значення.

Хешбел: Це спадковий клас, який розпізнається в рамках колекції.


Якщо це так, він повинен бути в коментарях не як відповідь.
манікантний гаутам

10

HashTable - це застарілий клас у jdk, який більше не слід використовувати. Замініть звичаї його на ConcurrentHashMap . Якщо вам не потрібна безпека потоку, використання HashMap , який не є поточно , але швидше і використовує менше пам'яті.


Тому що я думав, що інші відповіді в той час не відхилили HashTable, але пояснили, що це безпечно для потоків. Правда полягає в тому, що як тільки ви побачите HashTable у коді, вам слід замінити його на ConcurrentHashMap, не пропускаючи ритм. І якщо безпека ниток не викликає занепокоєння, тоді HashMap можна використовувати для покращення продуктивності.
jontejj

10
  1. Hashtableсинхронізовано, тоді HashMapяк ні.
  2. Ще одна відмінність полягає в тому, що ітератор у значенні " HashMapбезпечний", тоді як нумератор Hashtable- не. Якщо ви зміните карту під час ітерації, ви знаєте.
  3. HashMapдозволяє в ньому нульові значення, а Hashtableні.

3
Ітератор HashMap виходить з ладу, не працює з ладу. Ось чому у нас є ConcurrentHashMap, який дозволяє змінювати під час ітерації. Перевірте цю публікацію journaldev.com/122/…
Pankaj

9

HashMap і HashTable

  • Деякі важливі моменти щодо HashMap та HashTable. будь ласка, прочитайте нижче деталі.

1) Hashtable і Hashmap реалізують інтерфейс java.util.Map 2) І Hashmap, і Hashtable - це колекція на основі хеш-файлів. і робота над хешированием. так це схожість HashMap і HashTable.

  • Яка різниця між HashMap і HashTable?

1) Перша відмінність HashMap не є безпечною для потоків. Хоча HashTable є ThreadSafe
2) HashMap ефективніше, оскільки вона не є безпечною для потоків. в той час, як продуктивність Hashtable не є кращою, оскільки безпечна для потоків. тому декілька потоків не можуть одночасно отримати доступ до Hashtable.


2
Оголошення, оскільки ця відповідь в деяких аспектах невірна. Hashtable не реалізує інтерфейс Map, а лише розширює клас словника, який є застарілим.
Янніс Сермеццадіс

8

Hashtable:

Хештеб - це структура даних, яка зберігає значення пари ключ-значення. Це не дозволяє нулю і для клавіш, і для значень. Ви отримаєте, NullPointerExceptionякщо додасте нульове значення. Він синхронізований. Тож воно йде зі своєю вартістю. Лише один потік може отримати доступ до HashTable в певний час.

Приклад :

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 схожий на Hashtable, але він також приймає пару ключових значень. Це дозволяє нулю як для клавіш, так і для значень. Його ефективність краща, ніж HashTable, бо вона є unsynchronized.

Приклад:

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

HashMapемулюється і тому може бути використаний у GWT client codeтой час як Hashtableце не так.


Це всебічний опис відмінностей між двома апісами?
ІгорГанапольський

Так (sic!). Про це повинні знати усі розробники GWT.
понг

5

Стара і класична тема, просто хочу додати цей корисний блог, який пояснює це:

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

Блог Маніш Чхабра

5 основних відмінностей між HashMap і Hashtable

І HashMap, і Hashtable реалізують інтерфейс java.util.Map, але є деякі відмінності, які розробники Java повинні розуміти, щоб написати більш ефективний код. Станом на платформі Java 2 v1.2 клас Hashtable був модернізований для реалізації інтерфейсу Map, завдяки чому він став членом Java Collections Framework.

  1. Однією з головних відмінностей між HashMap і Hashtable є те, що HashMap не синхронізований, тоді як Hashtable є синхронізованим, що означає, що Hashtable є безпечним для потоків і може бути розділений між декількома потоками, але HashMap не може бути розподілений між декількома потоками без належної синхронізації. Java 5 представила ConcurrentHashMap, який є альтернативою Hashtable і забезпечує кращу масштабованість, ніж Hashtable в Java. Синхронізований означає, що лише один потік може змінювати хеш-таблицю в один момент часу. В основному це означає, що будь-який потік перед виконанням оновлення на хештелі повинен буде придбати замок на об'єкті, а інші чекатимуть звільнення блокування.

  2. Клас HashMap приблизно еквівалентний Hashtable, за винятком того, що він дозволяє нулі. (HashMap дозволяє нульові значення як ключові та значення, тоді як Hashtable не дозволяє нульових значень).

  3. Третя суттєва відмінність HashMap від Hashtable полягає в тому, що Iterator в HashMap є невдалим ітератором, тоді як нумератор для Hashtable не є і не кидає ConcurrentModificationException, якщо будь-яка інша нитка змінює карту структурно, додаючи або видаляючи будь-який елемент, крім власного видалення Iterator ( ) метод. Але це не є гарантованою поведінкою, і СП буде виконувати все можливе. Це також важлива різниця між перерахуванням та ітератором на Java.

  4. Ще одна помітна відмінність між Hashtable і HashMap полягає в тому, що через безпеку потоків і синхронізацію Hashtable набагато повільніше, ніж HashMap, якщо він використовується в середовищі з одиночним потоком. Отже, якщо вам не потрібна синхронізація, а HashMap використовується лише одним потоком, він виконує Hashtable на Java.

  5. HashMap не гарантує, що порядок карти залишатиметься постійним у часі.

Зауважте, що HashMap можна синхронізувати за допомогою

Map m = Collections.synchronizedMap(hashMap);

Підсумовуючи істотні відмінності між Hashtable і HashMap на Java, наприклад, безпека потоку та швидкість, і на основі цього використовуйте Hashtable лише тоді, коли вам абсолютно потрібна безпека потоку, якщо ви працюєте з Java 5, розгляньте можливість використання ConcurrentHashMap в Java.


ConcurrentHashMap не синхронізовано для читання, тоді як Hashtable є. Отже, якщо у вас є велика кількість операцій зчитування, що відбуваються одночасно з записом, Hashtable буде служити вам краще, якщо ви дбаєте про цілісність даних.
ІгорГанапольський

5

І HashMap, і Hashtable використовуються для зберігання даних у формі ключа та значення. Обидва використовують техніку хешування для зберігання унікальних ключів. ut Є багато відмінностей між класами HashMap і Hashtable, які наведені нижче.

введіть тут опис зображення


Приємного візуального резюме!
Nadjib Mami
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.