В большинстве языков программирования словари предпочтительнее хэш-таблиц. В чем причины этого?
Почему Словарь предпочтительнее Hashtable?
Ответ 1
Для того, что стоит, словарь есть хеш-таблица.
Если вы имели в виду "почему мы используем класс Dictionary вместо класса Hashtable?", тогда это простой ответ: словарь - это общий тип, Hashtable - нет. Это означает, что вы получаете безопасность типов с помощью словаря, потому что вы не можете вставить в него какой-либо случайный объект, и вам не нужно выставлять значения, которые вы вынимаете.
Ответ 2
Dictionary
< < → → Hashtable
:
- Общий < lt; → > Non-Generic
- Требуется собственную синхронизацию потоков < < < < < < < < < < < < < < < <
- Перечисленный элемент:
KeyValuePair
< < < < → > Перечислимый элемент:DictionaryEntry
- Более новый ( > .NET 2.0) < < lt; → > Старее (с .NET 1.0)
- находится в System.Collections.Generic < < < < < < < < < < < < < < < < <
- Запрос несуществующего ключа вызывает исключение < < < < < < < < < → > Запрос на несуществующий ключ возвращает null
- возможно немного быстрее для типов значений < lt; → бит медленнее (требуется бокс/распаковка) для типов значений
Dictionary
/ Hashtable
сходства:
- Оба являются внутренне hashtables == быстрый доступ к данным с множеством элементов в соответствии с ключом
- Оба требуют неизменяемые и уникальные ключи
- Ключи обоих нуждаются в собственном
GetHashCode()
методе
Похожие коллекции .NET(кандидаты для использования вместо словаря и Hashtable):
-
ConcurrentDictionary
- потокобезопасный (можно безопасно получить доступ к нескольким потокам одновременно) -
HybridDictionary
- оптимизированная производительность (для нескольких элементов, а также для многих элементов) -
OrderedDictionary
- значения могут быть доступны через индекс int (по порядку, в котором были добавлены элементы) -
SortedDictionary
- элементы автоматически отсортированы -
StringDictionary
- строго типизировано и оптимизировано для строк
Ответ 3
Потому что Dictionary
- это общий класс (Dictionary<TKey, TValue>
), так что доступ к его контенту безопасен по типу (т.е. вам не нужно отбрасывать из Object
, как это происходит с Hashtable
).
Сравнение
var customers = new Dictionary<string, Customer>();
...
Customer customer = customers["Ali G"];
к
var customers = new Hashtable();
...
Customer customer = customers["Ali G"] as Customer;
Однако Dictionary
реализуется как Hashtable
внутри, поэтому технически он работает одинаково.
Ответ 4
FYI: в .NET, Hashtable
является потокобезопасным для использования несколькими потоками чтения и одним потоком записи, а в Dictionary
общедоступные статические члены являются потокобезопасными, но любые члены экземпляра не гарантируются потокобезопасностью.
Из-за этого нам пришлось изменить все наши словари на Hashtable
.
Ответ 5
В .NET разница между Dictionary<,>
и HashTable
заключается прежде всего в том, что первый - это общий тип, поэтому вы получаете все преимущества дженериков в терминах проверки статического типа (и уменьшенного бокса, но это не " как люди, как правило, думают с точки зрения производительности - есть определенная стоимость памяти для бокса, хотя).
Ответ 6
Люди говорят, что Словарь такой же, как хеш-таблица.
Это не обязательно так. Хэш-таблица - это реализация словаря. Типичным в этом случае, и он может быть по умолчанию в .NET, но он по определению не единственный.
Вы могли бы также хорошо реализовать словарь со связанным списком или деревом поиска, это было бы не так эффективно (для некоторых показателей эффективности).
Ответ 7
Collections
и Generics
полезны для обработки группы объектов. В .NET все объекты коллекций попадают под интерфейс IEnumerable
, который, в свою очередь, имеет ArrayList(Index-Value))
и HashTable(Key-Value)
. После .NET framework 2.0 ArrayList
и HashTable
были заменены на List
и Dictionary
. Теперь ArrayList
и HashTable
больше не используются в современных проектах.
В отличие от HashTable
и Dictionary
, Dictionary
является общим, где Hastable
не является общим. Мы можем добавить любой тип объекта к HashTable
, но при извлечении нам нужно отбросить его до требуемого типа. Таким образом, это не безопасный тип. Но до Dictionary
, объявляя себя, мы можем указать тип ключа и значение, поэтому нет необходимости бросать при извлечении.
Посмотрим на пример:
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);
}
}
}
Ответ 8
Словарь:
-
Он возвращает/бросает исключение, если мы пытаемся найти ключ, который не существует.
-
Это быстрее, чем Hashtable, потому что нет бокса и unboxing.
-
Только публичные статические члены являются потокобезопасными.
-
Словарь - это общий тип, который означает, что мы можем использовать его с любым типом данных (при создании должны указывать типы данных для обоих ключей и значений).
Пример:
Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();
-
Dictionay - это безопасная по типу реализация Hashtable,
Keys
иValues
строго типизированы.
Hashtable:
-
Он возвращает null, если мы пытаемся найти ключ, который не существует.
-
Он медленнее, чем словарь, потому что он требует бокса и распаковки.
-
Все члены в Hashtable являются потокобезопасными,
-
Hashtable не является общим типом,
-
Hashtable - это структура данных без ввода символов, мы можем добавлять ключи и значения любого типа.
Ответ 9
Так как .NET Framework 3.5 также существует HashSet<T>
, который предоставляет все преимущества Dictionary<TKey, TValue>
, если вам нужны только ключи и нет значений.
Итак, если вы используете Dictionary<MyType, object>
и всегда устанавливаете значение null
для имитации безопасной хеш-таблицы типа, вы можете подумать о переходе на HashSet<T>
.
Ответ 10
В статье Обширная экспертиза структуры данных с использованием С# в MSDN указано, что существует также разница в стратегии стратегии устранения конфликтов:
Класс Hashtable использует технику, называемую rehashing.
Rehashing работает следующим образом: существует множество хеш-функций, H 1... H n, а при вставке или извлечении элемента из хэша table, изначально используется хэш-функция H 1. Если это приведет к столкновение, H 2, а затем до H n, если это необходимо.
Словарь использует технику, называемую цепочкой.
При повторном нажатии в случае столкновения хэш пересчитывается и проверяется новый слот, соответствующий хешу. Однако при цепочке используется вторичная структура данных для хранения любые столкновения. В частности, каждый слот в словаре имеет массив элементов, которые сопоставляются с этим ведром. В случае столкновения встречный элемент добавляется к списку ведер.
Ответ 11
Hashtable
- это структура данных с типизированной типизацией, поэтому вы можете добавить ключи и значения любого типа в Hashtable
. Класс Dictionary
представляет собой безопасную для типа Hashtable
реализацию, а ключи и значения строго типизированы. При создании экземпляра Dictionary
необходимо указать типы данных как для ключа, так и для значения.
Ответ 12
Обратите внимание, что MSDN говорит: "Словарь < (Of < (TKey, TValue > ) > ) класс реализуется как хэш-таблица ", а не "Словарь < (Of < (TKey, TValue > ) > ) реализуется как HashTable"
Словарь НЕ реализуется как HashTable, но реализуется в соответствии с концепцией хэш-таблицы. Реализация не связана с классом HashTable из-за использования Generics, хотя внутри Microsoft могла использовать тот же код и заменять символы типа Object на TKey и TValue.
В .NET 1.0 Generics не существует; здесь начались HashTable и ArrayList.
Ответ 13
Объект Hashtable состоит из ведер, содержащих элементы коллекции. Ведро - это виртуальная подгруппа элементов в Hashtable, , которая делает поиск и извлечение проще и быстрее, чем в большинстве коллекций.
Класс словаря имеет ту же функциональность, что и класс Hashtable. Словарь определенного типа (кроме объекта) имеет более высокую производительность, чем Hashtable для типов значений, поскольку элементы Hashtable имеют тип Object, и поэтому бокс и распаковка обычно возникают, если хранить или извлекать тип значения.
Для дальнейшего чтения: Hashtable и типы коллекции словарей
Ответ 14
Еще одно отличие, которое я могу выяснить:
Мы не можем использовать Dictionary < KT, VT > (generics) с веб-службами. Причина в том, что стандарт веб-службы не поддерживает стандарт дженериков.
Ответ 15
Dictionary<>
является универсальным типом, поэтому он безопасен.
Вы можете вставить любой тип значения в HashTable, и иногда это может вызвать исключение. Но Dictionary<int>
будет принимать только целочисленные значения и аналогично Dictionary<string>
будет принимать только строки.
Итак, лучше использовать Dictionary<>
вместо HashTable
.
Ответ 16
Другим важным отличием является то, что Hashtable является потокобезопасным. Hashtable имеет встроенную систему защиты многопотокового считывателя/одиночной записи (MR/SW), что означает, что Hashtable позволяет одиночной записи вместе с несколькими считывателями без блокировки.
В случае словаря нет безопасности потока; если вам нужна безопасность потоков, вы должны реализовать свою собственную синхронизацию.
Далее уточнить:
Hashtable обеспечивает некоторую безопасность потоков через свойство
Synchronized
, которое возвращает потокобезопасную оболочку вокруг коллекции. Обертка работает, блокируя всю коллекцию при каждой операции добавления или удаления. Поэтому каждый поток, пытающийся получить доступ к коллекции, должен дождаться, пока его очередь займет один замок. Это не является масштабируемым и может привести к значительной деградации производительности для больших коллекций. Кроме того, дизайн не полностью защищен от условий гонки.Классы коллекции .NET Framework 2.0, такие как
List<T>, Dictionary<TKey, TValue>
и т.д., не обеспечивают ни одной синхронизации потоков; код пользователя должен обеспечивать всю синхронизацию, когда элементы добавляются или удаляются одновременно на нескольких потоках.
Если вам нужна безопасность типов, а также безопасность потоков, используйте параллельные классы коллекций в .NET Framework. Дальнейшее чтение здесь.
Дополнительная разница заключается в том, что когда мы добавляем несколько записей в словаре, порядок, в который добавляются записи, поддерживается. Когда мы извлекаем предметы из Словаря, мы получим записи в том же порядке, в который мы их вставили. В то время как Hashtable не сохраняет порядок вставки.
Ответ 17
Во время выполнения операций Словарь выполняется быстрее, потому что нет бокса/распаковки (значениям нет необходимости в боксе), в то время как в боксе/распаковке Hashtable (важно, что нужно делать бокс), и которое может иметь потребление памяти, а также штрафы за производительность.
Когда мы добавляем несколько записей в словарь, порядок, в котором добавляются записи, сохраняется. Когда мы извлекаем предметы из Словаря, мы получим записи в том же порядке, в который мы их вставили. В то время как мы добавляем те же записи в Hashtable, заказ не поддерживается. Подробнее о.... Словарь и хеш-таблица
Rj
Ответ 18
HashTable:
Ключ/значение будет преобразовываться в тип объекта (бокс) при сохранении в кучу.
Ключ/значение необходимо преобразовать в желаемый тип во время чтения из кучи.
Эти операции очень дорогостоящие. Нам нужно как можно больше избежать бокса/распаковки.
Словарь: Общий вариант HashTable.
Нет бокса/распаковки. Конверсий не требуется.
Ответ 19
В соответствии с тем, что я вижу, используя .NET Reflector:
[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 внутренне использует HashTable.