Почему словарь предпочтительнее Hashtable?
в большинстве языков программирования, словари предпочтительнее, чем хеш-таблицы. Каковы причины этого?
18 ответов
для чего это стоит, словарь и (концептуально) хэш-таблице.
если вы имели в виду " почему мы используем Dictionary<TKey, TValue>
класс вместо Hashtable
класса?- тогда ответ прост:Dictionary<TKey, TValue>
универсального типа, Hashtable
нет. Это означает, что вы получаете тип безопасности с Dictionary<TKey, TValue>
, потому что вы не можете вставить в него случайный объект, и вам не нужно отбрасывать значения, которые вы берете.
интересно, что Dictionary<TKey, TValue>
реализация в .NET Framework на основе Hashtable
, как можно понять из этого комментария в исходном коде:
общий словарь был скопирован из источника Hashtable
Dictionary
>> Hashtable
отличия:
- Generic >> Non-Generic
- должен собственная синхронизация потоков >> предлагает thread safe версия через
Synchronized()
метод - перечисляемого элемента:
KeyValuePair
>> перечисляемого элемента:DictionaryEntry
- новее ( > .NET 2.0) >> старше (с .NET 1.0)
- находится в .Коллекции.Generic >> находится в .Сборники
- запрос на несуществующий ключ бросает исключение >> запрос на несуществующий ключ возвращает null
- потенциально немного быстрее для типов значений >> чуть медленнее (требуется бокс/распаковка) для значения типы
Dictionary
/ Hashtable
сходство:
- как внутренне хеш-таблицы == быстрый доступ к данным много-деталя согласно ключу
- как надо неизменяемые и уникальные ключи
- ключи обоих нужно иметь
GetHashCode()
метод
как .NET коллекции (кандидаты для использования вместо словаря и Хеш-таблицы):
-
ConcurrentDictionary
- thread safe (можно безопасно получить доступ из нескольких потоков одновременно) -
HybridDictionary
- оптимизация производительности (для немногих деталей и также для много деталей) -
OrderedDictionary
- значения могут быть доступ через int index (в порядке добавления элементов) -
SortedDictionary
- статьи автоматически сортируются -
StringDictionary
- со строгой типизацией и оптимизирован для строки
, потому что Dictionary
является общим классом (Dictionary<TKey, TValue>
), Так что доступ к его содержимому является типобезопасным (т. е. вам не нужно бросать из Object
, а ты Hashtable
).
сравнить
var customers = new Dictionary<string, Customer>();
...
Customer customer = customers["Ali G"];
to
var customers = new Hashtable();
...
Customer customer = customers["Ali G"] as Customer;
, Dictionary
реализуется как Hashtable
внутри, так что технически это работает точно так же.к вашему сведению: во .Чистая, Hashtable
является потокобезопасным для использования несколькими потоками чтения и одним потоком записи, в то время как в Dictionary
открытые статические члены являются потокобезопасными, но любые члены экземпляров не гарантируется потокобезопасность.
нам пришлось изменить все наши словари на Hashtable
из-за этого.
в .NET разница между Dictionary<,>
и HashTable
в первую очередь, что первый является общим типом, поэтому вы получаете все преимущества дженериков с точки зрения статической проверки типов (и уменьшенного бокса, но это не так велико, как люди склонны думать с точки зрения производительности - есть определенная стоимость памяти для бокса, хотя).
люди говорят, что словарь-это то же самое, что и хэш-таблица.
Это не обязательно так. Хэш-таблица-это реализация словаря. Типичный при этом, и он может быть по умолчанию в .NET, но он по определению не единственный.
вы также можете реализовать словарь со связанным списком или деревом поиска, он просто не будет таким эффективным (для некоторых показателей эффективности).
Collections
& Generics
полезны для обработки группы объектов. В .NET все объекты коллекций входят в интерфейс IEnumerable
, который в свою очередь ArrayList(Index-Value))
& HashTable(Key-Value)
. После .NET framework 2.0,ArrayList
& HashTable
заменить List
& Dictionary
. Теперь Arraylist
& HashTable
больше не используются в современных проектах.
подходя к разнице между HashTable
& Dictionary
, Dictionary
является общим, где as Hastable
не является универсальным. Мы можем добавить любой тип возражаю HashTable
, но при извлечении нам нужно привести его к требуемому типу. Таким образом, это не тип safe. Но ... --18-->, при объявлении себя мы можем указать тип ключа и значение, поэтому нет необходимости бросать при получении.
давайте рассмотрим пример:
HashTable
class HashTableProgram
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add(1, "One");
ht.Add(2, "Two");
ht.Add(3, "Three");
foreach (DictionaryEntry de in ht)
{
int Key = (int)de.Key; //Casting
string value = de.Value.ToString(); //Casting
Console.WriteLine(Key + " " + value);
}
}
}
словарь
class DictionaryProgram
{
static void Main(string[] args)
{
Dictionary<int, string> dt = new Dictionary<int, string>();
dt.Add(1, "One");
dt.Add(2, "Two");
dt.Add(3, "Three");
foreach (KeyValuePair<int, String> kv in dt)
{
Console.WriteLine(kv.Key + " " + kv.Value);
}
}
}
словарь:
возвращает/бросает исключение, если мы пытаемся найти ключ, который не существует.
это быстрее, чем хэш-таблица, потому что нет бокса и распаковки.
только общедоступные статические члены являются потокобезопасными.
-
словарь является общим типом, что означает, что мы можем использовать его с любым типом данных (при создании необходимо указать типы данных для обоих ключей и значения.)
пример:
Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();
- Диктивного тип-безопасная реализация Hashtable,
Keys
иValues
строго типизированы.
Hashtable:
он возвращает null, если мы пытаемся найти ключ, который не существует.
Это медленнее, чем словарь, потому что он требует упаковки и распаковки.
все члены в хэш-таблице являются потокобезопасными,
Hashtable не является общим типом,
Hashtable-это слабо типизированная структура данных, мы можем добавлять ключи и значения любого типа.
начиная с .NET Framework 3.5 существует также HashSet<T>
, который предоставляет все преимущества Dictionary<TKey, TValue>
если вам нужны только ключи и никакого значения.
если вы используете Dictionary<MyType, object>
и всегда устанавливайте значение null
чтобы имитировать тип безопасной хэш-таблицы, вы должны, возможно, рассмотреть вопрос о переключении на HashSet<T>
.
на обширное изучение структур данных с использованием C# в статье MSDN говорится, что существует также разница в стратегия разрешения столкновений:
класс Hashtable использует метод, называемый rehashing.
Rehashing работает следующим образом: существует набор хэш - функций, H1 ... Hn, и при вставке или извлечении элемента из хэш таблица, изначально H1 используется хэш-функция. Если это приводит к столкновение, H2 вместо этого пробуется и далее до Hn при необходимости.
словарь использует метод, называемый сцепление.
при повторном хэшировании в случае столкновения хэш пересчитывается, и пробуется новый слот, соответствующий хэшу. С цепями, однако,вторичная структура данных используется для хранения любые столкновения. В частности, каждый слот в словаре массив элементов, которые соответствуют этому ведру. В случае столкновения элемент colliding добавляется в список bucket.
на Hashtable
- это слабо типизированная структура данных, поэтому вы можете добавлять ключи и значения любого типа в Hashtable
. The Dictionary
класс является типобезопасным Hashtable
реализация, а ключи и значения строго типизированы. При создании Dictionary
экземпляр, необходимо указать типы данных как для ключа, так и для значения.
обратите внимание, что MSDN говорит: "класс Dictionary)>) реализован как хэш-таблицы", не " словарь)>) класс реализован как HashTable"
словарь не реализован как хэш-таблица, но он реализован в соответствии с концепцией хэш-таблицы. Реализация не связана с классом HashTable из-за использования дженериков, хотя внутренне Microsoft могла бы использовать тот же код и заменить символы типа Object с TKey и TValue.
в .NET 1.0 дженерики не существовали; именно здесь изначально начинались хэш-таблица и ArrayList.
объект Hashtable состоит из ведер, содержащих элементы коллекции. Ведро-это виртуальная подгруппа элементов в хэш-таблице,что делает поиск и извлечение проще и быстрее, чем во многих коллекциях.
класс Dictionary имеет ту же функциональность, что и класс Hashtable. Словарь определенного типа (кроме Object) имеет лучшую производительность, чем Hashtable для типов значений, потому что элементы Hashtable имеют тип Object и, следовательно, бокс и распаковка обычно происходят при сохранении или получении типа значения.
для дальнейшего чтения: Hashtable и словарь типов коллекции
HashTable:
ключ / значение будет преобразован в тип объекта (бокса) при хранении в куче.
ключ / значение необходимо преобразовать в нужный тип при чтении из кучи.
эти операции очень дорогостоящие. Нам нужно избегать бокса / распаковки как можно больше.
словарь : общий вариант HashTable.
нет бокс/распаковка. Преобразование не требуется.
еще одно отличие, которое я могу понять:
мы не можем использовать словарь
Dictionary<>
является общим типом,и поэтому он безопасен.
вы можете вставить любой тип значения в HashTable, и это иногда может вызвать исключение. Но!--1--> будет принимать только целочисленные значения, а так же Dictionary<string>
принимает только строки.
Итак, лучше использовать Dictionary<>
вместо HashTable
.
другое важное различие заключается в том, что Hashtable является потокобезопасным. Hashtable имеет встроенную множественную безопасность потока читателя/одиночного писателя (MR/SW) которая значит что Hashtable позволяет одному писателю вместе с множественными читателями без фиксировать.
в случае словаря нет безопасности потоков; если вам нужна безопасность потоков, вы должны реализовать свою собственную синхронизацию.
уточнения:
Hashtable обеспечивает некоторую поток-безопасность через
Synchronized
свойство, которое возвращает потокобезопасную оболочку вокруг коллекции. Обертка работает путем блокировки всей коллекции при каждой операции добавления или удаления. Поэтому каждый поток, который пытается получить доступ к коллекции, должен дождаться своей очереди, чтобы взять одну блокировку. Это не масштабируется и может привести к значительному снижению производительности для больших коллекций. Кроме того, конструкция не полностью защищена от условий гонки.классы коллекции .NET Framework 2.0 как
List<T>, Dictionary<TKey, TValue>
, etc. не предоставляйте синхронизацию потоков; код пользователя должен обеспечивать синхронизацию всех элементов при одновременном добавлении или удалении элементов в нескольких потоках
Если вам нужна безопасность типов, а также безопасность потоков, используйте параллельные классы коллекций в .NET Framework. Дальнейшее чтение здесь.
дополнительная разница заключается в том, что при добавлении нескольких записей в словаре сохраняется порядок добавления записей. Когда мы получим элементы из словаря, мы получим записи в том же порядке, в котором мы их вставили. В то время как Hashtable не сохраняет порядок вставки.
по тому что я вижу с помощью .Чистый отражатель:
[Serializable, ComVisible(true)]
public abstract class DictionaryBase : IDictionary, ICollection, IEnumerable
{
// Fields
private Hashtable hashtable;
// Methods
protected DictionaryBase();
public void Clear();
.
.
.
}
Take note of these lines
// Fields
private Hashtable hashtable;
поэтому мы можем быть уверены, что DictionaryBase использует хэш-таблицу внутри.