2009-05-18 15 views
95

Powiel możliwe:
Why Dictionary is preferred over hashtable in C#?Różnica między Słownik i Hashtable

Jaka jest różnica między Słownik i Hashtable. Jak zdecydować, którego użyć?

+2

Wygląda na to, że pytanie to powinno zostać zamknięte jako duplikat, a jego odpowiedzi połączone z jednym z duplikatów. –

+0

Mam nadzieję, że odpowiedzi na to [pytanie] (http://stackoverflow.com/questions/301371/why-dictionary-is-preferred-over-hashtable-in-c) zapewnia dobrą odpowiedź – TheVillageIdiot

+0

Chociaż związane z językiem Java, ale [ ten] (https://stackoverflow.com/q/40471/465053) wątek jest wart przeczytania, aby poznać różnicę między 'HashMap' i' HashTable'. Kilka różnic dotyczy również świata C#. – RBT

Odpowiedz

185

Wystarczy, Dictionary<TKey,TValue> to typ rodzajowy, pozwalając:

  • statycznego typowania (i kompilacji czas weryfikacji)
  • używanie bez boksu

Jeśli .NET 2.0 lub nowszy, powinieneś woliszDictionary<TKey,TValue> (i inne ogólne kolekcje)

Subtelne, ale ja Istotną różnicą jest to, że Hashtable obsługuje wiele wątków czytnika z jednym wątkiem zapisu, a Dictionary nie zapewnia bezpieczeństwa wątków. Jeśli potrzebujesz zabezpieczenia wątków za pomocą ogólnego słownika, musisz zaimplementować własną synchronizację lub (w .NET 4.0) użyć ConcurrentDictionary<TKey, TValue>.

+3

Ale metody instancji języka Dictionary nie są bezpieczne dla wątków, w przeciwieństwie do tabeli Hashtable – t3mujin

11

Słownik jest wpisany (więc typy wartości nie wymagają boksowania), a Hashtable nie jest (tak, że wartości są potrzebne do boksowania). Hashtable ma lepszy sposób na uzyskanie wartości niż słownikowe IMHO, ponieważ zawsze wie, jaką wartością jest obiekt. Chociaż jeśli używasz .NET 3.5, łatwo jest napisać metodę rozszerzenia dla słownika, aby uzyskać podobne zachowanie.

Jeśli potrzebujesz wiele wartości na klucz, sprawdź mój źródłowego z MultiValueDictionary tutaj: multimap in .NET

+2

Dla wielu wartości na klucz: w .NET 3.5, możesz również rozważyć implementację 'ILookup ' (który jest interfejsem wielu map). Niestety domyślna implementacja jest niezmienna, ale jest łatwa do ponownego wdrożenia (lub dodania do MultiValueDictionary). Jest prosty przykład takiego w MiscUtil (EditableLookup ) –

+0

Dobra wskazówka, zapomniałem o tym interfejsie. Spojrzałem na implementację w BCL, ale w rzeczywistości jest niezmienne, prawie bezużyteczne w codziennym użytkowaniu wielowartościowym;). Dodam interfejs. –

+0

Gotowe. Ponownie opublikowany kod: http://weblogs.asp.net/fbouma/archive/2009/05/18/multi-value-dictionary-c-source-code-net-3-5.aspx –

6

Hashtable klasa jest specyficznym rodzajem klasie słownika, który wykorzystuje wartość całkowitą (tzw hash) do pomocy w przechowywanie kluczy. Klasa Hashtable używa skrótu do przyspieszenia wyszukiwania określonego klucza w kolekcji. Każdy obiekt w .NET pochodzi z klasy Object. Ta klasa obsługuje metodę GetHash, która zwraca liczbę całkowitą, która jednoznacznie identyfikuje obiekt. Klasa Hashtable jest ogólnie bardzo wydajną kolekcją. Jedynym problemem związanym z klasą HashTable jest to, że wymaga niewielkiego nakładu pracy, a w przypadku małych kolekcji (mniej niż dziesięć elementów) obciążenie może utrudnić działanie.

jest jakaś specjalna różnica między nimi, które należy wziąć pod uwagę:

HashTable: to zbiór non-generic, największy narzut tym kolekcji jest to, że automatycznie robi boks dla wartości i w celu Aby uzyskać oryginalną wartość, musisz wykonać rozpakowywanie, , aby zmniejszyć wydajność aplikacji jako karę.

słownik: To jest rodzajowy typu kolekcji, w których nie niejawna boks, więc nie ma potrzeby, aby unboxing będziesz zawsze dostać oryginalne wartości, które zostały zapisane tak pan poprawi aplikacja wydajność.

Druga różnica jest znaczny:

jeśli były próby dostępu na wartości z tabeli mieszania na podstawie klucza, który nie istnieje powróci null.But w przypadku Słownik Będzie daje wyjątek KeyNotFoundException.

+0

Moje komentarze pochodzą z książki MCTS 2.0, a jej dostał -ve rep ... jak ironiczny !!!! : D –

+2

Niezbyt ironiczny ... zarówno Hashtable jak i Dictionary <,> opierają się na tym podejściu, więc w żaden sposób nie odpowiada na pytanie o wybór między nimi. –

+4

Prawdziwa ironia polega na tym, że czytałem tę samą książkę MCTS, naprawdę nie wiedziałem, który z nich wolę, opublikowałem tutaj i otrzymałem ten sam tekst, który właśnie przeczytałem w formie odpowiedzi! :) Dziękuję za odpowiedź na pytania .. – blitzkriegz

19

Jest jeszcze jedna ważna różnica między HashTable i Dictionary. Jeśli użyjesz indeksatorów, aby uzyskać wartość z HashTable, HashTable zwróci wartość null dla nieistniejącego elementu, podczas gdy słownik wygeneruje błąd, jeśli spróbujesz uzyskać dostęp do elementu za pomocą indeksu, który nie istnieje w Słowniku

3

Interfejs ILookup jest używany w .net 3.5 z linq.

The HashTable jest klasą podstawową, która jest słabo typu; Klasa abstrakcyjna DictionaryBase jest ściśle napisana i wykorzystuje wewnętrznie HashTable.

Znalazłem dziwną rzecz o Słowniku, gdy dodamy wiele wpisów w Słowniku, kolejność, w której wpisy są dodawane, jest zachowywana. Jeśli więc zastosuję foreach w Słowniku, otrzymam rekordy w takiej samej kolejności, w jakiej je wstawiłem.

To nie jest prawda w normalnym HashTable, ponieważ gdy dodaję te same rekordy w Hashtable, kolejność nie zostanie zachowana. O ile mi wiadomo, Słownik jest oparty na HashTable, jeśli to prawda, dlaczego mój słownik utrzymuje kolejność, ale HashTable nie?

Co do tego, dlaczego zachowują się inaczej, to dlatego, że Słownik ogólny implementuje hashtable, ale nie jest oparty na System.Collections.Hashtable. Implementacja słownika ogólnego opiera się na alokowaniu par klucz-wartość z listy. Są one następnie indeksowane z zasobnikami hashtable dla dostępu losowego, ale kiedy zwraca moduł wyliczający, po prostu idzie po liście w kolejności sekwencyjnej - która będzie kolejnością wstawiania tak długo, jak wpisy nie będą ponownie używane.

Shiv govind Birlasoft. :)

75

Pozwala dać przykład, że byłoby wyjaśnić różnicę między hashtable i słownika.

Oto metoda, która implementuje hashtable

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; 
    //} 
} 

Poniżej dla słownika

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; 
    } 
    } 
+5

Doskonała !!!!!!!!!!!!! – nawfal

+0

Super i proste –

+3

Dobra odpowiedź. Zawsze lepiej wyjaśnić za pomocą przykładów niż teoria pisania. – Kenta

10

chcesz dodać różnicę:

Próbując acess kluczowym nieistniejące daje czas pracy błąd w słowniku, ale nie ma problemu z hashtable, ponieważ zwraca null zamiast błędu.

np.

 //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 

tu żadnego błędu na przycisk 0 & także na przycisk „dziesięć” (uwaga: T jest mała)

//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]); 

tutaj błędu dla kluczowej 0 & także dla klucza 10, oba są nieobecne w słowniku , błąd środowiska wykonawczego, podczas próby uzyskania dostępu.

+0

Przypuszczam, że powinieneś używać 'LINQ' do znajdź element 'FirstOrDefault', jeśli próbujesz pracować z kolekcją poza foreach i dla. – ppumkin