Hashtable, HashMap, HashSet, концепция хеш-таблицы в платформе коллекции Java
Я изучаю Java Collection Framework и получил умеренное понимание. Теперь, когда я иду немного дальше, у меня есть некоторые сомнения в: HashMap
, HashSet
, Hashtable
,
Javadoc для HashMap
говорит:
Реализация интерфейса карты на основе хеш-таблицы. Эта реализация предоставляет все необязательные операции с картами и допускает нулевые значения и нулевой ключ.
Javadoc для HashSet
говорит:
Этот класс реализует интерфейс Set, поддерживаемый хеш-таблицей (фактически, экземпляром HashMap). Это не дает никаких гарантий относительно порядка итераций множества; в частности, это не гарантирует, что порядок останется неизменным с течением времени.
Javadoc для Hashtable
говорит:
Этот класс реализует хеш-таблицу, которая отображает ключи на значения. Любой ненулевой объект может использоваться как ключ или как значение.
Забавно, что все они реализуют hash table
, Они реализуют концепцию хэш-таблицы?
Кажется, что все они связаны друг с другом, но я не могу полностью понять это.
Может ли кто-нибудь помочь мне понять эту концепцию на простом языке.
4 ответа
В Java Set
а также Map
интерфейсы определяют два очень разных типа коллекции. Map
концептуально это то, на что это похоже: отображение одного набора объектов (ключей) в другой набор (значений). Set
это также как звучит: коллекция объектов (без какой-либо другой структуры). Hashtable
а также HashMap
оба реализуют Map
, HashSet
инвентарь Set
и все они используют хеш-коды для ключей / объектов, содержащихся в коллекциях, для повышения производительности.
Hashtable
а такжеHashMap
Hashtable
это унаследованный класс, которого почти всегда следует избегать в пользу HashMap
, Они делают по существу то же самое, за исключением большинства методов в Hashtable
синхронизируются, что делает отдельные вызовы метода потокобезопасными.1 Вы должны предоставить собственную синхронизацию или другой механизм безопасности потоков, если вы используете несколько потоков и HashMap
,
Проблема с Hashtable
заключается в том, что синхронизация каждого вызова метода (что является немаловажной операцией) обычно неправильная вещь. Либо вам вообще не нужна синхронизация, либо, с точки зрения логики приложения, вам нужно синхронизировать транзакции, которые охватывают несколько вызовов методов. Поскольку было невозможно просто удалить синхронизацию на уровне метода из Hashtable
не нарушая существующий код, авторам платформы Collections нужно было придумать новый класс; следовательно HashMap
, Это также лучшее имя, так как становится ясно, что это своего рода Map
,
О, если вам нужна синхронизация на уровне метода, вы все равно не должны использовать Hashtable
, Вместо этого вы можете позвонить Collections.synchronizedMap()
превратить любую карту в синхронизированную. Кроме того, вы можете использоватьConcurrentHashMap
, который, согласно документам: "подчиняется той же функциональной спецификации, что и Hashtable
"но имеет лучшую производительность и дополнительную функциональность (например,putIfAbsent()
).
1Существуют и другие различия (на мой взгляд, менее значимые), такие как HashMap
поддержки null
ценности и ключи.
HashSet
С точки зрения функциональности, HashSet
не имеет ничего общего с HashMap
, Случается использовать HashMap
внутренне для реализации Set
функциональность. По какой-то причине разработчики платформы Collections решили, что было бы неплохо сделать эту деталь внутренней реализации частью публичной спецификации для класса. (Это была ошибка, на мой взгляд.)
Hashtable был старым классом, который был создан до того, как в Java появились дженерики. Это только вокруг для обратной совместимости. Вместо этого используйте HashMap.
Используйте HashSet, когда вам не нужно сопоставлять ключи со значениями. Он построен по тому же алгоритму, что и хеш-таблицы, но используется для принципиально иной цели.
HashMap и HashTable оба наследуют интерфейс Map.и имеют почти одинаковые рабочие свойства и свойства. Но основные различия заключаются в следующем:
1.Hashmap - это неупорядоченная карта пар ключ и значение. И у нас может быть нулевой ключ или пары значений внутри hashmap. Также hashmap является несинхронизированным (т. Е. Не безопасным для потоков, несколько потоков могут получать к нему доступ и изменять его одновременно). Но мы можем внешне сделать hashmap thread-safe.So, если мы не рассматриваем проблемы синхронизации, тогда hashmap предпочтительнее.
2.HashTable:- Синхронизированная hashMap (т. Е. Потокобезопасная hashmap). Но пары ключей и значений в этом случае никогда не будут нулевыми. В Hashtable мы указываем объект, который используется в качестве ключа, и значение, которое мы хотим ассоциировать с этим ключом. Затем ключ хешируется, и полученный хеш-код используется в качестве индекса, по которому значение сохраняется в таблице.
3.HashSet:-Hashset наследует установленный интерфейс и, в конце концов, он также основан на hashtable(или мы можем сказать, что он тесно связан только с нашей hashmap), но в этом случае пары ключей и значений всегда уникальны, повторяющиеся значения не допускаются. Но null допустимы значения ключей. Объекты вставляются на основе их хэш-кода.
В заключение можно сказать, что все три коллекции подключены к интерфейсу Map и все.
Hashtable синхронизируется, а HashMap - нет, но вы можете настроить синхронизацию HashMap с помощью метода Collections.synchronizedMap() . Hashtable, HashMap и HashSet работают на основе структуры данных Hash Table. Вы можете использовать один нулевой ключ и какой тип нулевых значений вы хотите для HashMap, но Hashtable не допускает нулевой ключ или нулевые значения. В основном под HashSet работает HashMap, где значением является Object, поэтому значения HashSet уникальны, потому что ключи HashMap уникальны. Таким образом, для помещения пары ключ-значение в Hashmap или Hashtable или для помещения элемента в HashSet вам необходимо переопределить hashcode и методы равные из класса Object, чтобы исправить работу этих реализаций. Это связано с тем, что при данной реализации работают алгоритм хэш-таблицы и хэш-код, равные требуются для помещения значений в правильное ведро. Важно знать, что вам нужно использовать в качестве ключей String или любой другой класс-обертку, такой как Integer, это потому, что эти объекты являются неизменяемыми и могут быть хорошими ключами для этих реализаций, или вы можете создать свой собственный неизменяемый класс и использовать его в качестве ключа, Использование неизменяемых объектов в качестве ключа является хорошей практикой, поскольку после создания они не могут изменить свое состояние, следовательно, хэш-код всегда один и тот же.