Различия между HashMap и Hashtable? - PullRequest
       311

Различия между HashMap и Hashtable?

3465 голосов
/ 03 сентября 2008

Каковы различия между HashMap и Hashtable в Java?

Что более эффективно для непоточных приложений?

Ответы [ 34 ]

3521 голосов
/ 03 сентября 2008

Существует несколько различий между HashMap и Hashtable в Java:

  1. Hashtable является синхронизированным , тогда как HashMap - нет. Это делает HashMap лучше для не поточных приложений, поскольку несинхронизированные объекты обычно работают лучше, чем синхронизированные.

  2. Hashtable не допускает null ключи или значения. HashMap допускает одну клавишу null и любое количество значений null.

  3. Один из подклассов HashMap - LinkedHashMap, поэтому в случае, если вам нужен предсказуемый порядок итераций (по умолчанию это порядок вставки), вы можете легко заменить HashMap за LinkedHashMap. Это было бы не так просто, если бы вы использовали Hashtable.

Поскольку синхронизация не является для вас проблемой, я бы порекомендовал HashMap. Если синхронизация становится проблемой, вы также можете посмотреть на ConcurrentHashMap.

631 голосов
/ 03 сентября 2008

Обратите внимание, что во многих ответах говорится, что Hashtable синхронизирован. На практике это очень мало для вас. Синхронизация по методам доступа / мутатора остановит одновременное добавление или удаление двух потоков из карты, но в реальном мире вам часто потребуется дополнительная синхронизация.

Очень распространенная идиома - «проверить, затем положить» - то есть найти запись в Map и добавить ее, если она еще не существует. Это ни в коем случае не атомарная операция, используете ли вы Hashtable или HashMap.

Эквивалентно синхронизированный HashMap может быть получен:

Collections.synchronizedMap(myMap);

Но для правильной реализации этой логики вам потребуется дополнительная синхронизация вида:

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

Даже перебор записей Hashtable (или HashMap, полученных с помощью Collections.synchronizedMap) не является потокобезопасным, если вы также не защитите Map от изменения посредством дополнительной синхронизации.

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

ConcurrentMap.putIfAbsent(key, value);
327 голосов
/ 25 июня 2009

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

169 голосов
/ 04 октября 2011

Этот вопрос часто задают на собеседовании, чтобы проверить, понимает ли кандидат правильное использование классов сбора и знает ли он о доступных альтернативных решениях.

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

Карта обеспечивает представления Коллекции вместо прямой поддержки итерации через перечисление объектов. Представления коллекции значительно увеличивают Выразительность интерфейса, о чем пойдет речь далее в этом разделе. Карта позволяет перебирать ключи, значения или пары ключ-значение; Hashtable не предоставляет третий вариант. Карта обеспечивает безопасный способ удалить записи в разгар итерации; Hashtable нет. Наконец, Map исправляет незначительный недостаток интерфейса Hashtable. В Hashtable есть метод с названием contains, который возвращает true, если Hashtable содержит заданное значение. Учитывая его название, вы ожидаете это метод, чтобы возвратить истину, если Hashtable содержал данный ключ, потому что ключ является основным механизмом доступа для Hashtable. Карта Интерфейс устраняет этот источник путаницы, переименовывая метод containsValue. Кроме того, это улучшает согласованность интерфейса - Содержит значение параллели содержит ключ.

Интерфейс карты

121 голосов
/ 03 сентября 2008

HashMap: реализация интерфейса Map, который использует хэш-коды для индексации массива. Hashtable: Привет, 1998 позвонил. Они хотят вернуть свои коллекции API.

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

115 голосов
/ 25 марта 2014

Имейте в виду, что HashTable был унаследованным классом до появления Java Collections Framework (JCF) и позднее был модернизирован для реализации интерфейса Map. Так было Vector и Stack.

Поэтому всегда избегайте их в новом коде, поскольку в JCF всегда есть лучшая альтернатива, как указывали другие.

Вот чит-лист Java collection , который вы найдете полезным. Обратите внимание, что серый блок содержит устаревшие классы HashTable, Vector и Stack.

enter image description here

62 голосов
/ 03 сентября 2008

В дополнение к тому, что сказал izb, HashMap допускает нулевые значения, тогда как Hashtable - нет.

Также обратите внимание, что Hashtable расширяет класс Dictionary, который как состояние Javadocs устарел и был заменен интерфейсом Map.

58 голосов
/ 06 марта 2017

Есть много хороших ответов уже опубликовано. Я добавляю несколько новых пунктов и обобщаю их.

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.

Hashtable

  1. Hashtable синхронизируется. Это потокобезопасный и может использоваться многими потоками.
  2. Hashtable не допускает нулевой ключ или значение.
  3. Hashtable - унаследованный класс.
  4. Hashtable медленно.
  5. Hashtable внутренне синхронизировано и не может быть несинхронизировано.
  6. Hashtable проходит через перечислитель и итератор.
  7. Перечислитель в Hashtable не работает быстро.
  8. Hashtable наследует класс словаря.

Дополнительная литература В чем разница между HashMap и Hashtable в Java?

enter image description here

54 голосов
/ 20 ноября 2012

Посмотрите на этот график. Это обеспечивает сравнение между различными структурами данных наряду с HashMap и Hashtable. Сравнение точное, ясное и простое для понимания.

Матрица Java-коллекции

45 голосов
/ 03 сентября 2008

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

...