Питання Відмінності між HashMap і Hashtable?


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

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


3122
2017-09-02 20:12


походження


HashTable застаріла в Java 1.7 і рекомендується використовувати ConcurrentMap реалізації - MissFiona


Відповіді:


Є кілька відмінностей між ними HashMap і Hashtable в Java:

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

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

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

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


3207
2017-09-02 23:02



Якщо ви хочете зробити схему HashMap безпечною, скористайтеся Collections.synchronizedMap(). - Rok Strniša
Я хотів би також прокоментувати це наївний підхід до потоку безпеки в Hashtable ("синхронізація кожного методу повинна подбати про будь-які проблеми паралельності!") робить це дуже сильно гірше для різьбових програм. Вам краще зовні синхронізувати a HashMap (і мислення про наслідки), або використання ConcurrentMap реалізація (і використання його розширеного API для паралельності). Підсумок: єдина причина для використання Hashtable це коли потрібно застарілий API (починаючи з 1996 року). - erickson
HashMap надає програмісту можливість генерувати код threadSafe, коли він насправді використовує його. Мені рідко траплялося, що мені потрібна безпечна колекція, така як ConcurrentHashMap або HashTable. Мені потрібно було певний набір функцій або певних операцій в синхронізованому блоці, щоб бути безпечним для вікон. - Gaurava Agarwal
Hashtable є застарілим, і ми використовуємо HashMap для безпечного середовища, не пов'язаного з потоками. Якщо вам потрібна безпека потоку, ви можете використовувати Collections.synchronizedMap () або використовувати ConcurrentHashMap, що є більш ефективним, ніж хешбайт. - Maneesh Kumar
Це застаріла, але не застаріла, і мені цікаво, чому це таке. Я гадаю, що видалення цього класу (і Vector з тих самих причин) буде зламати занадто багато існуючого коду і анотування з @Deprecated означатиме намір видалити код, який, мабуть, там не існує. - Jilles van Gurp


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

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

Аналогічно синхронізований HashMap можна отримати за допомогою:

Collections.synchronizedMap(myMap);

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

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

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

Реалізація ConcurrentMap інтерфейс (наприклад ConcurrentHashMap) вирішити деякі з них шляхом включення thread безпечна перевірка-то-дія семантика як от:

ConcurrentMap.putIfAbsent(key, value);

583
2017-09-03 11:00



Також зауважте, що якщо змінена HashMap, ітератори, які вказують на неї, відображаються недійсними. - Chris K
Ітератор викине ConcurrentModificationException, чи не так? - Bhushan
Чи існує якась різниця між синхронізованими (myMap) {...} та ConcurrentHashMap з точки зору безпеки в потоці? - telebog
Дуже вірно, я спробував пояснити саме тут ..lovehasija.com/2012/08/16/... - Love Hasija
@ Бхушан: це буде кидати на найкращому рівні, це не гарантована поведінка: docs.oracle.com/javase/7/docs/api/java/util/HashMap.html - Matt Stephenson


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


288
2018-06-25 01:46



З Hashtable javadoc (додано наголос): "Що стосується платформи Java 2 версії 1.2, то цей клас був модернізований для реалізації інтерфейсу" Карта " роблячи його членом Framework Java Collections"Тим не менш, ви маєте рацію, що це спадщина коду. Всі переваги синхронізації можна отримати більш ефективно з Collections.synchronizedMap (HashMap) (подібно до того, що Vector є застарілою версією Collections.synchronizedList (ArrayList)). - Kip
@ aberrant80: на жаль, ви не маєте вибору між цими двома і маєте використовувати Hashtable при програмуванні для J2ME ... - pwes
цю відповідь слід видалити. він містить невірну інформацію та має багато переваг. - anon58192932
@ anon58192932 Чи можна редагувати запитання, щоб виправити це? - GC_
Ми повинні привернути увагу плаката @ aberrant80 або адміністратора, позначивши його. Позначення може допомогти - спробуйте це зараз. - anon58192932


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

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

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

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

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

Map m = Collections.synchronizeMap(hashMap);

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

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


148
2017-10-04 06:39



Ця відповідь містить принаймні 2 суттєвих фактичних неточностей. Це, безумовно, НЕ заслуговує на те, що це багато оновлень. - Stephen C
1) Ітератори HashMap НЕ БЕЗКОШТОВНО. Вони провалилися швидко. Існує величезна різниця в значенні між цими двома термінами. 2) немає set операція на a HashMap. 3) The put(...) операція не буде кидати IllegalArgumentException якщо була попередня зміна. 4) Безвідмовна поведінка HashMap  також відбувається, якщо ви змінюєте відображення. 5) Безвідмовна поведінка є гарантовано (Що не гарантується, є поведінка a HashTable якщо ви робите одночасну модифікацію. Фактична поведінка є ... непередбачуваною.) - Stephen C
6) Hashtable не гарантує, що порядок елементів мапи з часом буде стабільним. (Ви, можливо, заплутуєте Hashtable з LinkedHashMap.) - Stephen C
Будь-який інший дійсно стурбований тим, що студенти в наші дні отримують неправду ідею про те, що отримання "синхронізованих версій" колекцій дещо означає, що вам не потрібно зовнішньо синхронізувати складні операції? Мій улюблений приклад цього буття thing.set(thing.get() + 1); який частіше за все змушує новачків зненацька абсолютно незахищеним, особливо якщо get() і set() є синхронізованими методами. Багато хто з них чекає магії.
Ітератори на HashMap не є безпечними - Abdul


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

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


107
2017-09-02 23:14



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


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

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

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

enter image description here


104
2018-03-25 08:58





На додаток до того, що сказав Ізб, HashMap дозволяє нульовим значенням, в той час як Hashtableне.

Також зауважте, що Hashtable продовжує Dictionary клас, який як і Джавадоч держава, застаріла і була замінена Map інтерфейс


58
2017-09-02 20:30



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


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

Матриця збірки Java


50
2017-11-20 05:35



дякую, тепер я знаю, що вибрати у моєму сценарії. - Well Smith