Разница между словарем и Hashtable [дубликат]

Возможный дубликат:
почему словарь предпочтительнее хеш-таблицы в C #?

В чем разница между словарем и Hashtable. Как решить, какой использовать?

18.05.2009 07:55:02
надеюсь, ответы на этот вопрос
TheVillageIdiot 18.05.2009 07:58:15
Похоже, этот вопрос следует закрыть как дубликат, а его ответы объединить с одним из дубликатов.
John Saunders 18.05.2009 11:07:23
Хотя это связано с языком Java, но этот поток стоит прочитать, чтобы знать разницу между HashMapи HashTable. Немного различий применимо и к миру C #.
RBT 11.08.2017 03:10:15
7 ОТВЕТОВ
РЕШЕНИЕ

Просто, Dictionary<TKey,TValue>это универсальный тип, позволяющий:

  • статическая типизация (и проверка во время компиляции)
  • использовать без бокса

Если вы используете .NET 2.0 или выше, вы должны предпочесть Dictionary<TKey,TValue> (и другие универсальные коллекции)

Тонкое, но важное отличие состоит в том, что Hashtableподдерживает несколько потоков чтения с одним потоком записи, но не Dictionaryобеспечивает безопасности потока. Если вам нужна безопасность потоков с общим словарем, вы должны реализовать свою собственную синхронизацию или (в .NET 4.0) использование ConcurrentDictionary<TKey, TValue>.

194
3.05.2011 16:53:49
Но методы экземпляра словаря не являются потокобезопасными, в отличие от Hashtable
t3mujin 15.07.2010 10:38:25

Словарь набирается (таким образом, значения типа не нуждаются в боксе), Hashtable - нет (поэтому значения типа нужны бокс). У Hashtable есть более хороший способ получения значения, чем у словаря IMHO, потому что он всегда знает, что значение является объектом. Хотя, если вы используете .NET 3.5, легко написать метод расширения для словаря, чтобы получить похожее поведение.

Если вам нужно несколько значений для каждого ключа, посмотрите мой исходный код MultiValueDictionary здесь: multimap в .NET

12
23.05.2017 12:26:17
Для нескольких значений на ключ: в .NET 3.5 вы также можете рассмотреть возможность реализации ILookup<TKey,TValue>(это интерфейс с несколькими картами). К сожалению, конкретная реализация по умолчанию является неизменной, но ее легко повторно реализовать (или добавить в свой MultiValueDictionary). Вот простой пример такого в MiscUtil (EditableLookup <TKey, TValue>)
Marc Gravell♦ 18.05.2009 08:01:49
Хороший совет, я забыл об этом интерфейсе. Я посмотрел на реализацию в BCL, но она действительно неизменна, поэтому практически бесполезна для повседневного использования с несколькими значениями;). Я добавлю интерфейс.
Frans Bouma 18.05.2009 08:08:46
Выполнено. Переиздан код: weblogs.asp.net/fbouma/archive/2009/05/18/…
Frans Bouma 18.05.2009 09:06:37
Хм, есть проблема с ILookup <>: он также реализует Enumerator, который отличается от перечислителя Dictionary. Когда оператор Linq используется в многозначном словаре, он не может выбрать, какой перечислитель использовать, поскольку он также может использовать IEnumerable <TKey, IGrouping <TKey, TValue >>, даже если ILookup реализован явно ... Что затрудняет используйте словарь, так как он требует явной спецификации типов.
Frans Bouma 18.05.2009 10:10:18
MultiDictionary также присутствует в PowerCollections: www.wintellect.com/powercollections.aspx
Dmitri Nesteruk 17.08.2010 11:08:22

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

Существует некоторая особая разница между двумя, которую необходимо учитывать:

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

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

Вторым существенным отличием является:

если вы пытаетесь получить доступ к значению из хеш-таблицы на основе несуществующего ключа, он вернет null. Но в случае Dictionary он выдаст вам KeyNotFoundException.

6
3.10.2017 22:14:17
Мои комментарии взяты из книги MCTS 2.0, и она получила -ve репутацию ... как иронично !!!! : D
SO User 18.05.2009 11:27:04
Не очень иронично ... Hashtable и Dictionary <,> основаны на этом подходе, поэтому он никоим образом не отвечает на вопрос выбора между ними.
Marc Gravell♦ 18.05.2009 11:46:44
Настоящая ирония в том, что я читал одну и ту же книгу MCTS, действительно запутался в том, какую книгу выбрать, разместил ее здесь и получил тот же текст, который я только что прочитал в форме вашего ответа !!! :) Спасибо за ответ nyways ..
blitzkriegz 18.05.2009 12:26:26

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

23
16.03.2010 03:04:45

Интерфейс ILookup используется в .net 3.5 с linq.

HashTable - это базовый класс слабого типа; абстрактный класс DictionaryBase строго типизирован и использует внутри себя HashTable.

Я обнаружил странную вещь в словаре, когда мы добавляем несколько слов в словаре, порядок, в котором они добавляются, сохраняется. Таким образом, если я применю foreach к Словарю, я получу записи в том же порядке, в котором я их вставил.

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

Что касается того, почему они ведут себя по-разному, это потому, что Общий словарь реализует хеш-таблицу, но не основан на System.Collections.Hashtable. Реализация общего словаря основана на выделении пар ключ-значение из списка. Затем они индексируются с помощью хеш-таблиц для произвольного доступа, но когда он возвращает перечислитель, он просто просматривает список в последовательном порядке - это будет порядок вставки, если записи не используются повторно.

Шив Говинд Birlasoft. :)

3
4.07.2010 20:12:56

Давайте приведем пример, который объясняет разницу между хэш-таблицей и словарем.

Вот метод, который реализует хеш-таблицу

public void MethodHashTable()
{
    Hashtable objHashTable = new Hashtable();
    objHashTable.Add(1, 100);    // int
    objHashTable.Add(2.99, 200); // float
    objHashTable.Add('A', 300);  // char
    objHashTable.Add("4", 400);  // string

    lblDisplay1.Text = objHashTable[1].ToString();
    lblDisplay2.Text = objHashTable[2.99].ToString();
    lblDisplay3.Text = objHashTable['A'].ToString();
    lblDisplay4.Text = objHashTable["4"].ToString();


    // ----------- Not Possible for HashTable ----------
    //foreach (KeyValuePair<string, int> pair in objHashTable)
    //{
    //    lblDisplay.Text = pair.Value + " " + lblDisplay.Text;
    //}
}

Следующее для словаря

  public void MethodDictionary()
  {
    Dictionary<string, int> dictionary = new Dictionary<string, int>();
    dictionary.Add("cat", 2);
    dictionary.Add("dog", 1);
    dictionary.Add("llama", 0);
    dictionary.Add("iguana", -1);

    //dictionary.Add(1, -2); // Compilation Error

    foreach (KeyValuePair<string, int> pair in dictionary)
    {
        lblDisplay.Text = pair.Value + " " + lblDisplay.Text;
    }
  }
83
10.01.2011 11:49:16
Как примечание ..... вы можете перечислить свойства Hashtable, как описано здесь: msdn.microsoft.com/en-us/library/… . Вы должны использовать DictionaryEntry в качестве переменной, которая затем может предоставлять объекты ключа и значения.
jedd.ahyoung 30.05.2014 15:40:00
Превосходный ответ, также вы можете использовать DictionaryEntry для перечисления по Hashtable.Ex: foreach (DictionaryEntry dnty в objHashTable) {lblDisplay.Text = dnty.Value + "" + dnty.Key}
Manoj Weerasooriya 18.12.2014 04:30:55
// Цикл hastable foreach (запись DictionaryEntry в objHashTable) {Console.WriteLine ("{0}, {1}", entry.Key, entry.Value); }
Mike 9.10.2018 03:03:17

Хочу добавить разницу:

Попытка доступа к несуществующему ключу приводит к ошибке времени выполнения в словаре, но нет проблем в хеш-таблице, поскольку она возвращает ноль вместо ошибки.

например

       //No strict type declaration
        Hashtable hash = new Hashtable();
        hash.Add(1, "One");
        hash.Add(2, "Two");
        hash.Add(3, "Three");
        hash.Add(4, "Four");
        hash.Add(5, "Five"); 
        hash.Add(6, "Six");
        hash.Add(7, "Seven");
        hash.Add(8, "Eight");
        hash.Add(9, "Nine");
        hash.Add("Ten", 10);// No error as no strict type

        for(int i=0;i<=hash.Count;i++)//=>No error for index 0
        {
            //Can be accessed through indexers
            Console.WriteLine(hash[i]);
        }
        Console.WriteLine(hash["Ten"]);//=> No error in Has Table

здесь нет ошибки для ключа 0, а также для ключа «десять» (примечание: t мало)

//Strict type declaration
        Dictionary<int,string> dictionary= new Dictionary<int, string>();
        dictionary.Add(1, "One");
        dictionary.Add(2, "Two");
        dictionary.Add(3, "Three");
        dictionary.Add(4, "Four");
        dictionary.Add(5, "Five");
        dictionary.Add(6, "Six");
        dictionary.Add(7, "Seven");
        dictionary.Add(8, "Eight");
        dictionary.Add(9, "Nine");
        //dictionary.Add("Ten", 10);// error as only key, value pair of type int, string can be added

        //for i=0, key doesn't  exist error
        for (int i = 1; i <= dictionary.Count; i++)
        {
            //Can be accessed through indexers
            Console.WriteLine(dictionary[i]);
        }
        //Error : The given key was not present in the dictionary.
        //Console.WriteLine(dictionary[10]);

здесь ошибка для ключа 0 и также для ключа 10, так как оба отсутствуют в словаре, ошибка во время выполнения, при попытке доступа.

10
6.07.2011 09:50:25
Я полагаю, что вы должны использовать, LINQчтобы найти FirstOrDefaultэлемент, если вы пытаетесь работать с коллекцией вне foreach и для.
Piotr Kula 12.03.2014 09:57:28