Вопрос-ответ

What are the differences between a HashMap and a Hashtable in Java?

В чем разница между хэш-картой и хэш-таблицей в Java?

В чем разница между HashMap и a Hashtable в Java?

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

Переведено автоматически
Ответ 1

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


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



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



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



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

Ответ 2

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

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

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

Collections.synchronizedMap(myMap);

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

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

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

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

ConcurrentMap.putIfAbsent(key, value);
Ответ 3

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

Ответ 4

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


  1. HashMap Класс примерно эквивалентен Hashtable , за исключением того, что он несинхронизирован и допускает значения null. (HashMap допускает нулевые значения в качестве ключа и значения, тогда как Hashtable не допускает null значений).

  2. HashMap не гарантирует, что порядок отображения будет оставаться постоянным с течением времени.

  3. HashMap не синхронизирован, тогда как Hashtable синхронизирован.

  4. Итератор в HashMap является отказоустойчивым, в то время как перечислитель для Hashtable нет, и выбрасывает, ConcurrentModificationException если какой-либо другой поток изменяет карту структурно, добавляя или удаляя любой элемент, кроме Iteratorсобственного remove() метода. Но это не гарантированное поведение и будет выполнено JVM при максимальном старании.

Обратите внимание на некоторые важные термины:


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

  2. Отказоустойчивость актуальна в контексте итераторов. Если итератор был создан для объекта коллекции и какой-либо другой поток пытается изменить объект коллекции "структурно", будет выдано исключение параллельной модификации. Однако другие потоки могут вызывать метод set, поскольку он не изменяет коллекцию "структурно". Однако, если перед вызовом set коллекция была структурно изменена, она IllegalArgumentException будет выброшена.

  3. Структурная модификация означает удаление или вставку элемента, который может эффективно изменить структуру карты.

HashMap может быть синхронизирован с помощью

Map m = Collections.synchronizeMap(hashMap);

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


Интерфейс Map


java collections