Почему Словарь предпочтительнее 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.