Dlaczego Słownik jest preferowany przez Hashtable w C#?

W większości języków programowania preferowane są słowniki zamiast hashtabli. Jakie są tego powody?

Author: kristianp, 2008-11-19

19 answers

Jeśli to coś warte, Słownik jest (koncepcyjnie) tabelą hash.

Jeśli miałeś na myśli "dlaczego używamy klasy Dictionary<TKey, TValue> zamiast klasy Hashtable?", wtedy jest to łatwa odpowiedź: Dictionary<TKey, TValue> jest typem ogólnym, Hashtable nie jest. Oznacza to, że otrzymujesz zabezpieczenie typu za pomocą Dictionary<TKey, TValue>, ponieważ nie możesz wstawić do niego żadnego przypadkowego obiektu i nie musisz rzucać wartości, które wyjmujesz.

Co ciekawe, implementacja Dictionary<TKey, TValue> W. NET Framework opiera się na Hashtable, Jak widać z ten komentarz w kodzie źródłowym:

Słownik generyczny został skopiowany ze źródła Hashtable

Źródło

 1616
Author: Michael Madsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-15 12:52:41

Dictionary >> Hashtable różnice:

  • Generic >> Non-Generic
  • wymaga własnej synchronizacji wątków >> oferty thread safe Wersja poprzez Synchronized() metoda
  • pozycja wyliczona: KeyValuePair >> pozycja wyliczona: DictionaryEntry
  • Newer (>. NET 2.0) >> starsze (od . NET 1.0)
  • jest w System.Kolekcje.Generic >> jest w systemie .Kolekcje
  • żądanie do nieistniejącego klucza rzuca wyjątek >> Request to nieistniejący klucz zwraca null
  • potencjalnie bit szybszy dla typów wartości >> bit wolniejszy (wymaga boksu/unboxingu) dla typów wartości

Dictionary / Hashtable podobieństwa:

  • oba są wewnętrznie hashtables = = szybki dostęp do wielu pozycji danych według klucza
  • oba potrzebują niezmiennych i unikalnych kluczy
  • Klucze obu muszą posiadać GetHashCode() metoda

Podobne kolekcje. NET (kandydaci do użycia zamiast słownika i Hashtable):

  • ConcurrentDictionary - thread safe (może być bezpiecznie dostępny z kilku wątków jednocześnie)
  • HybridDictionary - zoptymalizowana wydajność (dla kilku elementów, a także dla wielu elementów)
  • OrderedDictionary - wartości mogą być dostępne za pomocą indeksu int (według kolejności, w jakiej elementy zostały dodane)
  • SortedDictionary - pozycje sortowane automatycznie
  • StringDictionary - silnie typowane i zoptymalizowane dla ciągów
 642
Author: Marcel Toth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-15 09:59:08

Ponieważ Dictionary jest klasą generyczną (Dictionary<TKey, TValue> ), więc dostęp do jej zawartości jest bezpieczny dla typu(tzn. nie musisz rzucać z Object, Jak to robisz z Hashtable).

Porównaj

var customers = new Dictionary<string, Customer>();
...
Customer customer = customers["Ali G"];

Do

var customers = new Hashtable();
...
Customer customer = customers["Ali G"] as Customer;

Jednak {[2] } jest zaimplementowana wewnętrznie jako tabela hash, więc technicznie działa w ten sam sposób.

 185
Author: gius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-19 20:58:45

FYI: w. NET, {[0] } jest bezpieczny dla wątków dla wielu czytników i jednego wątku do pisania, podczas gdy w Dictionary public static członkowie są bezpieczni dla wątków, ale członkowie instancji nie mają gwarancji, że będą bezpieczni dla wątków.

Musieliśmy zmienić wszystkie nasze słowniki z powrotem na Hashtable z tego powodu.

 92
Author: user38902,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 08:00:20

W. NET różnica między Dictionary<,> i HashTable polega przede wszystkim na tym,że ten pierwszy jest typem generycznym, więc otrzymujesz wszystkie zalety generycznych pod względem statycznego sprawdzania typów (i zmniejszonego boksu, ale nie jest to tak duże, jak ludzie myślą w kategoriach wydajności - Boks ma określony koszt pamięci).

 71
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-19 09:54:50

Ludzie mówią, że słownik jest tym samym, co tabela hash.

To niekoniecznie prawda. Tabela hash jest jednym ze sposobów implementacji słownika. Typowa i może być domyślna w. Net w klasie Dictionary, ale nie jest z definicji jedyna.

Równie dobrze można zaimplementować słownik za pomocą listy linkowanej lub drzewa wyszukiwania, po prostu nie byłoby to tak efektywne(dla niektórych metryk efektywności).

 35
Author: rix0rrr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-19 21:04:46

Collections & Generics są przydatne do obsługi grup obiektów. W. NET wszystkie obiekty collections znajdują się pod interfejsem IEnumerable, który z kolei ma ArrayList(Index-Value)) & HashTable(Key-Value). Po. NET framework 2.0, ArrayList & HashTable zostały zastąpione przez List & Dictionary. Teraz,Arraylist & HashTable nie są już wykorzystywane w dzisiejszych projektach.

Dochodząc do różnicy między HashTable & Dictionary, Dictionary jest generyczny, gdzie as {[16] } nie jest generyczny. Możemy dodać dowolny typ obiektu do HashTable, ale podczas pobierania musimy go oddać do wymaganego typu. Więc nie jest bezpieczny. Ale do dictionary, deklarując się możemy określić typ klucza i wartość, więc nie ma potrzeby rzucać podczas pobierania.

Spójrzmy na przykład:

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

    }
}

Słownik,

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);
        }
    }
}
 24
Author: Sujit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 08:14:45

Słownik:

  • Zwraca / rzuca wyjątek, jeśli spróbujemy znaleźć klucz, który nie istnieje.

  • Jest szybszy niż Hashtable, ponieważ nie ma boksu i unboxingu.

  • Tylko public static members are thread safe.

  • Słownik jest typem generycznym, co oznacza, że możemy go używać z dowolnym typem danych(podczas tworzenia należy określić typy danych zarówno dla kluczy, jak i wartości).

    Przykład: Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();

  • Dictionay jest implementacją Hashtable, Keys i Values są silnie wpisane.

Hashtable:

  • Zwraca null, jeśli spróbujemy znaleźć klucz, który nie istnieje.

  • Jest wolniejszy od słownika, ponieważ wymaga boksu i unboxingu.

  • Wszyscy członkowie w Hashtable są bezpieczni dla wątków,

  • Hashtable nie jest typem generycznym,

  • Hashtable to luźno typowana struktura danych, możemy dodawać klucze i wartości dowolnego typu.

 18
Author: Altaf Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-25 05:23:40

The Extensive Examination of Data Structures Using C# article on MSDN states that there is also a difference in the collision resolution strategy :

Klasa Hashtable wykorzystuje technikę określaną jako rehashing .

Rehashing działa w następujący sposób: istnieje zbiór różnych funkcji hash, H1 ... Hn , a podczas wstawiania lub pobierania elementu z hasha tabela, początkowo H1 funkcja hash jest używany. Jeśli prowadzi to do kolizja, H2 jest próbowany zamiast tego, i dalej do H n w razie potrzeby.

Słownik używa techniki zwanej łańcuchowaniem .

Przy ponownym obliczaniu, w przypadku kolizji hash jest ponownie obliczany, a nowy slot odpowiadający hashowi jest próbowany. Z chaining, jednak Drugorzędna struktura danych jest wykorzystywana do przechowywania wszelkie kolizje . Konkretnie, każdy slot w słowniku ma tablicę elementów, które mapują do tego wiadra. W przypadku kolizji, element kolidujący jest dołączany do listy wiadra.

 18
Author: alexandrekow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-18 11:35:50

Od. NET Framework 3.5 istnieje również HashSet<T> który zapewnia wszystkie zalety Dictionary<TKey, TValue> jeśli potrzebujesz tylko kluczy i żadnych wartości.

Więc jeśli używasz Dictionary<MyType, object> i zawsze ustawiasz wartość na null, aby symulować tabelę hashową typu safe, powinieneś rozważyć przejście na HashSet<T>.

 18
Author: Oliver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 08:15:58

Hashtable jest luźno wpisaną strukturą danych, więc możesz dodać klucze i wartości dowolnego typu do Hashtable. Klasa Dictionary jest implementacją bezpieczną dla typu Hashtable, a klucze i wartości są mocno wpisywane. Podczas tworzenia instancji Dictionary należy określić typy danych zarówno dla klucza, jak i wartości.

 16
Author: flesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-14 05:19:47

Zwróć uwagę, że Dokumentacja mówi: "Klasa Dictionary)>) jest zaimplementowana jako tabela hash", a nie "klasa Dictionary)>) jest zaimplementowana jako HashTable"

Słownik nie jest zaimplementowany jako HashTable, ale jest zaimplementowany zgodnie z koncepcją tabeli hash. Implementacja nie jest powiązana z klasą HashTable ze względu na użycie Generics, chociaż wewnętrznie Microsoft mógł użyć tego samego kodu i zastąpiono symbole obiektu typu TKey i TValue.

W. NET 1.0 Generyki nie istniały; to tutaj pierwotnie rozpoczął się HashTable i ArrayList.

 14
Author: Brant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-03 15:14:59

HashTable:

Klucz / wartość zostanie przekonwertowana na typ obiektu (Boks) podczas przechowywania w stercie.

Klucz / wartość musi zostać przekonwertowana na żądany typ podczas odczytu ze sterty.

Te operacje są bardzo kosztowne. Musimy unikać boksu/rozpakowywania jak najwięcej.

Słownik: ogólny wariant HashTable.

No boxing/unboxing. Konwersje nie są wymagane.

 10
Author: Siva Sankar Gorantla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 08:19:25

Obiekt Hashtable składa się z wiadra, które zawierają elementy kolekcji. Bucket jest wirtualną podgrupą elementów w Hashtable, , która sprawia, że wyszukiwanie i wyszukiwanie jest łatwiejsze i szybsze niż w większości kolekcji.

Klasa słownika ma taką samą funkcjonalność jak Klasa Hashtable. Słownik określonego typu (innego niż obiekt) ma lepszą wydajność niż Hashtable dla typów wartości, ponieważ elementy Hashtable są typu Obiekt i, w związku z tym, boks i unboxing zazwyczaj występują, jeśli przechowywanie lub pobieranie typu wartości.

Do dalszej lektury: typy kolekcji Hashtable i Dictionary

 8
Author: mparkuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 10:51:13

Kolejną ważną różnicą jest to, że Hashtable jest bezpieczny dla wątku. Hashtable ma wbudowane zabezpieczenie wątku multiple reader/single writer (MR/SW), co oznacza, że Hashtable umożliwia jeden writer razem z wieloma czytnikami bez blokowania.

W przypadku słownika nie ma bezpieczeństwa wątku; jeśli potrzebujesz bezpieczeństwa wątku, musisz zaimplementować własną synchronizację.

Do dalszego rozwinięcia:

Hashtable zapewnia pewne bezpieczeństwo wątku poprzez Właściwość Synchronized, która zwraca bezpieczną owijkę wokół kolekcji. Owijarka działa poprzez zablokowanie całej kolekcji przy każdej operacji dodawania lub usuwania. Dlatego każdy wątek, który próbuje uzyskać dostęp do kolekcji, musi czekać na swoją kolej, aby wziąć jedną blokadę. Nie jest to skalowalne i może spowodować znaczny spadek wydajności dla dużych kolekcji. Ponadto konstrukcja nie jest całkowicie chroniona przed warunkami wyścigowymi.

Klasy kolekcji. NET Framework 2.0, takie jak List<T>, Dictionary<TKey, TValue>, itp. nie zapewnia synchronizację wątków; kod użytkownika musi zapewnić całą synchronizację, gdy elementy są dodawane lub usuwane w wielu wątkach jednocześnie

Jeśli potrzebujesz bezpieczeństwa typu, a także bezpieczeństwa wątku, użyj klas współbieżnych kolekcji w. NET Framework. Czytaj dalej tutaj .

Dodatkową różnicą jest to, że gdy dodamy wiele wpisów w słowniku, kolejność dodawania wpisów jest zachowana. Gdy pobieramy pozycje ze słownika, otrzymają zapisy w tej samej kolejności, w jakiej je wstawiliśmy. Podczas gdy Hashtable nie zachowuje kolejności wstawiania.

 8
Author: NullReference,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 08:18:33

Jeszcze jedna różnica, którą mogę rozgryźć to:

Nie możemy używać słownika(generics) z usługami sieciowymi. Powodem jest brak web service standard obsługuje standard generics.

 5
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 08:05:50

Dictionary<> jest typem generycznym, więc jest bezpieczny.

Możesz wstawić dowolny typ wartości w HashTable, co może czasami spowodować wystąpienie wyjątku. Ale Dictionary<int> będzie akceptować tylko wartości całkowite i podobnie Dictionary<string> będzie akceptować tylko ciągi znaków.

Dlatego lepiej używać Dictionary<> zamiast HashTable.

 5
Author: Kishore Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 08:12:51

W większości języków programowania preferowane są słowniki zamiast hashtabli

Myślę, że nie jest to koniecznie prawda, większość języków ma jeden lub drugi, w zależności od terminologii preferują .

W C# jednak oczywistym powodem (dla mnie) jest to, że C# i inni członkowie systemu.Przestrzenie nazw kolekcji są w dużej mierze przestarzałe. Były obecne w c # V1. 1. Zostały zastąpione z C # 2.0 przez klasy generyczne w System.Kolekcje.Ogólna przestrzeń nazw.

 0
Author: kristianp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-06 01:58:11

Według tego co widzę używając . 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;

Więc możemy być pewni, że DictionaryBase używa HashTable wewnętrznie.

 -3
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 08:12:07