it-swarm.com.ru

Почему словарь предпочтительнее, чем Hashtable в C #?

В большинстве языков программирования словари предпочтительнее хеш-таблиц. Каковы причины этого?

1307
Nakul Chaudhary

Для чего это стоит, словарь является (концептуально) хеш-таблицей.

Если вы имели в виду "почему мы используем класс Dictionary<TKey, TValue> вместо класса Hashtable?", То это простой ответ: Dictionary<TKey, TValue> является универсальным типом, а Hashtable - нет. Это означает, что вы получаете безопасность типов с помощью Dictionary<TKey, TValue>, потому что вы не можете вставить в нее какой-либо случайный объект и вам не нужно приводить значения, которые вы извлекаете.

Интересно, что реализация Dictionary<TKey, TValue> в .NET Framework основана на Hashtable, как вы можете заметить из этого комментария в его исходном коде:

Общий словарь был скопирован из источника Hashtable

Источник

1498
Michael Madsen

Dictionary <<< >>> Hashtable различия:

  • Универсальный <<< >>> Универсальный
  • Требуется синхронизация собственного потока <<< >>> Предложения потокобезопасен версия через Synchronized() метод
  • Перечисляемый элемент: KeyValuePair <<< >>> Перечисляемый элемент: DictionaryEntry
  • Более новые (> . NET 2.) <<< >>> Старые (начиная с . NET 1.)
  • находится в System.Collections.Generic <<< >>> находится в System.Collections
  • Запрос на несуществующий ключ выдает исключение <<< >>> Запрос на несуществующий ключ возвращает ноль
  • потенциально немного быстрее для типов значений <<< >>> немного медленнее (требуется бокс/распаковка) для типов значений

Dictionary/Hashtable сходства:

  • Оба они внутренне hashtables == быстрый доступ к данным из многих элементов в соответствии с ключом
  • Оба нужны неизменяемые и уникальные ключи
  • Ключи обоих требуют собственного GetHashCode() метод

Похожие Коллекции .NET (кандидаты для использования вместо Dictionary и Hashtable):

  • ConcurrentDictionary - потокобезопасен (можно безопасно получить доступ из нескольких потоков одновременно)
  • HybridDictionary - оптимизированная производительность (для нескольких элементов, а также для многих элементов)
  • OrderedDictionary - значения могут быть доступны через индекс int (по порядку, в котором элементы были добавлены)
  • SortedDictionary - элементы автоматически сортируются
  • StringDictionary - строго типизировано и оптимизировано для строк
597
Thetam

Поскольку 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 реализована как хеш-таблица внутри, поэтому технически она работает так же.

173
gius

К сведению: В .NET Hashtable является поточно-ориентированным для использования несколькими потоками читателей и одним потоком записи, тогда как в Dictionary публичные статические члены являются поточно-ориентированными, но не гарантируется, что любые члены экземпляра будут поточно-ориентированными.

Из-за этого нам пришлось изменить все наши словари обратно на Hashtable.

84
user38902

В .NET разница между Dictionary<,> и HashTable заключается, прежде всего, в том, что первый тип является универсальным типом, поэтому вы получаете все преимущества универсальных типов с точки зрения статической проверки типов (и сокращения бокса, но это не так велико, как люди склонны думаю, с точки зрения производительности - есть определенная стоимость памяти для бокса, хотя).

67
Marc Gravell

Люди говорят, что словарь такой же, как хеш-таблица.

Это не обязательно правда. Хеш-таблица является одним из способов реализовать словарь. Типичный для этого, и он может быть по умолчанию в .NET в классе Dictionary, но по определению он не единственный.

С таким же успехом вы могли бы реализовать словарь, используя связанный список или дерево поиска, это было бы не так эффективно (по некоторым показателям эффективности).

32
rix0rrr

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);
        }
    }
}
22
Sujit

Словарь:

  • Он возвращает/выдает Exception, если мы пытаемся найти ключ, который не существует.

  • Это быстрее, чем Hashtable, потому что там нет упаковки и распаковки.

  • Только открытые статические члены являются потокобезопасными.

  • Словарь - это универсальный тип, который означает, что мы можем использовать его с любым типом данных (при создании необходимо указывать типы данных как для ключей, так и для значений).

    Пример: Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();

  • Dictionay - это безопасная для типов реализация Hashtable, Keys и Values строго типизированы.

Hashtable:

  • Он возвращает ноль, если мы пытаемся найти ключ, который не существует.

  • Это медленнее, чем словарь, потому что он требует упаковки и распаковки.

  • Все члены Hashtable являются потокобезопасными,

  • Hashtable не является универсальным типом,

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

16
Altaf Patel

В статье Обширный анализ структур данных с использованием C # о MSDN говорится, что существует также разница в стратегии разрешения коллизий :

Класс Hashtable использует технику, называемую перефразировка .

Перефразировка работает следующим образом: есть множество различных функций хеширования, H1 ... Hnи при вставке или извлечении элемента из хеш-таблицы, первоначально H1 хэш-функция используется. Если это приводит к столкновению, H2 вместо этого пробуют и далее до Hn если нужно.

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

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

15
alexandrekow

Начиная с .NET Framework 3.5 есть также HashSet<T> , который предоставляет все преимущества Dictionary<TKey, TValue> , если вам нужны только ключи и никакие значения.

Поэтому, если вы используете Dictionary<MyType, object> и всегда устанавливаете значение null для имитации типовой безопасной хеш-таблицы, вам, возможно, стоит подумать о переключении на HashSet<T> .

14
Oliver

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

12
flesh

Обратите внимание, что MSDN говорит: "Словарь <(Of <(TKey, TValue>)>) класс реализован как хеш-таблица", а не" словарь <(Of <(TKey, TValue>)>) реализован как Хеш-таблица"

Словарь НЕ реализован как HashTable, но он реализован в соответствии с концепцией хеш-таблицы. Реализация не связана с классом HashTable из-за использования Generics, хотя внутри Microsoft могла бы использовать тот же код и заменить символы типа Object на TKey и TValue.

В .NET 1.0 Generics не существовало; именно здесь изначально начинались HashTable и ArrayList.

11
Brant

HashTable:

Ключ/значение будет преобразован в тип объекта (бокс) при сохранении в куче.

Ключ/значение необходимо преобразовать в нужный тип при чтении из кучи.

Эти операции очень дороги. Нам нужно как можно больше избегать коробок/распаковок.

Словарь: Общий вариант HashTable.

Нет бокса/распаковки. Никаких преобразований не требуется.

8
Siva Sankar Gorantla

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

Класс Dictionary имеет ту же функциональность, что и класс Hashtable. Словарь определенного типа (кроме Object) имеет лучшую производительность, чем Hashtable для типов значений, потому что элементы Hashtable имеют тип Object и, следовательно, , упаковка и распаковка обычно происходят при сохранении или получении типа значения.

Для дальнейшего чтения: Типы Hashtable и Коллекция словарей

8
mparkuk

Еще одно отличие, которое я могу понять:

Мы не можем использовать словарь <KT, VT> (generics) с веб-сервисами. Причина в том, что ни один стандарт веб-службы не поддерживает стандарт дженериков.

6
prashant

Dictionary<> является универсальным типом, поэтому он безопасен.

Вы можете вставить любой тип значения в HashTable, и это может иногда вызывать исключение. Но Dictionary<int> будет принимать только целочисленные значения и аналогично Dictionary<string> будет принимать только строки.

Таким образом, лучше использовать Dictionary<> вместо HashTable.

6
Kishore Kumar

Еще одно важное отличие состоит в том, что Hashtable является потокобезопасным. Hashtable имеет встроенную безопасность потоков для нескольких считывателей/писателей (MR/SW), что означает, что Hashtable позволяет ОДНОМ записывающему устройству вместе с несколькими считывателями без блокировки.

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

Чтобы уточнить дальше:

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

Классы коллекций .NET Framework 2.0, такие как List<T>, Dictionary<TKey, TValue> и т.д., Не обеспечивают никакой синхронизации потоков; код пользователя должен обеспечивать всю синхронизацию, когда элементы добавляются или удаляются в нескольких потоках одновременно

Если вам нужна безопасность типов, а также безопасность потоков, используйте классы одновременных коллекций в .NET Framework. Дальнейшее чтение здесь .

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

6
NullReference

В большинстве языков программирования словари предпочтительнее хеш-таблиц

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

Однако в C # очевидная причина (для меня) состоит в том, что C # HashTables и другие члены пространства имен System.Collections в значительной степени устарели. Они присутствовали в c # V1.1. Они были заменены из C # 2.0 классами Generic в пространстве имен System.Collections.Generic.

0
kristianp