.NET HashTable Vs Sözlük - Sözlük kadar hızlı olabilir mi?


276

Ne zaman ve neden bir sözlük veya HashTable kullanmak için anlamaya çalışıyorum. Burada biraz arama yaptım ve insanların tamamen katıldığım Sözlüğün genel avantajlarından bahsettiklerini gördüm, bu da hafif bir performans kazancı için boks ve kutudan çıkarma avantajına yol açıyor.

Ama aynı zamanda Sözlük her zaman yerleştirildikleri sırayla nesneleri döndürmez, sıralanan şey okudum. Nerede bir HashTable olacak. Anladığım kadarıyla bu, HashTable'ın bazı durumlar için çok daha hızlı olmasına yol açar.

Benim sorum gerçekten, bu durumlar ne olabilir? Yukarıdaki varsayımlarımda yanlış mıyım? Birini üst üste seçmek için hangi durumları kullanabilirsiniz (evet sonuncusu biraz belirsiz).


5
Bunu yükseltmek istemiyorum, ama karmanız 7.777 ve bunu sizin için berbat eden adam olmak istemiyorum.
CaptainMarvel

Yanıtlar:


298

System.Collections.Generic.Dictionary<TKey, TValue>ve System.Collections.Hashtablesınıfların her ikisi de bir karma tablo veri yapısını dahili olarak muhafaza eder. Hiçbiri öğelerin sırasını korumayı garanti etmez.

Boks / kutudan çıkarma sorunlarını bir kenara bırakarak, çoğu zaman çok benzer performansa sahip olmalıdırlar.

Aralarındaki birincil yapısal fark, çarpışmaları çözmek için zincirlemeye (her bir karma tablo kovası için bir öğe listesi tutmaya) Dictionarydayanırken, çarpışma çözünürlüğü için yeniden şekillendirme kullanır (bir çarpışma meydana geldiğinde, anahtarı bir kovaya eşlemek için başka bir karma işlevini dener) .Hashtable

Hashtable.NET Framework 2.0 ve sonraki sürümlerini hedefliyorsanız sınıf kullanmanın pek bir yararı yoktur . Etkili bir şekilde eskimiş hale geldi Dictionary<TKey, TValue>.


21
@ Jon- Zincirleme ve rehashing burada derinlemesine tartışıldı- msdn.microsoft.com/en-us/library/ms379571(VS.80).aspx
RichardOD

İkinize de teşekkürler. Richard'ın yayınladığı bu sayfayı buldum ... Zincirleme hakkında soracaktım ama MSDN sitesi gerçekten yardımcı oldu!
Jon

6
@Mehrdad - Çarpışmaların nasıl çözüldüğü hakkında net olmayan şey şudur: Birden fazla anahtar aynı karma ile sonuçlanabilirse, aramalarda doğru değeri aldığınızdan nasıl emin olursunuz, yani işlev hangi öğeyi dönüş? In msdn.microsoft.com/en-us/library/ms379571%28VS.80%29.aspx , sözlük basitçe zincirler herhangi çarpışmalar Hashtable sınıfı ile yapıldığı gibi o, bir çarpışma anında tekrar prob daha "yerine diyor kova listesine ekleyin. " Bu, Dictionary'i kullanırken çarpışmaların geliştiricinin endişe etmesi gereken bir şey olmadığı anlamına mı geliyor?
Howiecamp

6
@Howiecamp: Bu gerçekten çok farklı değil Hashtable. Karma tablolar bir girişte 3 parça bilgi depolar: anahtar karması, anahtarın kendisi ve değer. Eşit karması olan öğeler için, öğeyi eşit anahtarla bulmak ve değerini döndürmek için listeden geçmesi gerekir. Bu da oldukça doğru Hashtable. DictionaryNormal olarak kullanan bir geliştirici olarak, endişelenmenize gerek yoktur.
Mehrdad Afshari

@Mehrdad Sadece açık olmak gerekirse, hem Hashtable hem de Dictionary nesneleri anahtarın kendisini saklar ve her ikisi de çarpışmaları geliştiriciden gizler mi?
Howiecamp

111

Sanırım şu an sana bir şey ifade etmiyor. Ama sadece uğraşan insanlar için referans için

Performans Testi - SortedList vs. SortedDictionary vs. Sözlük vs. Hashtable

Bellek ayırma:

Bellek kullanımı performans testi

Ekleme için kullanılan süre:

Ekleme için kullanılan zaman

Bir öğeyi arama zamanı:

Bir öğeyi arama zamanı


Sıralanan listenin hashtable'dan daha hızlı bir aramaya sahip olması çok ilginç. Ben hashtable O (1) vs sıralanmış liste O (logn) olduğunu düşündüm. Görünüşe göre hashtable berbat. Asla kullanmayacağım.
John Henckel

@JohnHenckel no, sıralanmış liste daha yavaş aramaya sahip. Daha büyük performans katsayısı, daha iyi performans ve daha iyi bellek kullanımı anlamına gelir. Bu nedenle, sıralı liste grafiklere göre en iyi bellek kullanımına sahiptir, ancak ekleme ve arama gibi diğer alanlarda berbattır.
C0DEF52

31

Hashtable ve Sözlük arasındaki farklar

Sözlük:

  • Varolmayan bir anahtar bulmaya çalışırsak sözlük hata döndürür.
  • Bir Hashtable daha hızlı sözlük çünkü boks ve unboxing yoktur.
  • Sözlük genel bir türdür, yani herhangi bir veri türüyle kullanabiliriz.

hashtable'a:

  • Var olmayan bir anahtarı bulmaya çalışırsak Hashtable null değerini döndürür.
  • Hashtable sözlükten daha yavaştır, çünkü boks ve kutudan çıkarma gerektirir.
  • Hashtable genel bir tür değildir,

24

Bir başka önemli fark, Hashtable türünün aynı anda kilitsiz çoklu okuyucuları ve tek bir yazarı desteklemesi, ancak Sözlük desteklememesidir.


8
Eşzamanlı Sözlük (.Net 4.0)
Tamilmaran

1
Bu cevabı anladığımdan emin değilim. Buradan bakıldığında msdn.microsoft.com/en-us/library/… "Birden fazla yazarın desteklenmesi için Hashtable nesnesini okuyan hiçbir iş parçacığı olmaması koşuluyla, Hashtable'daki tüm işlemlerin Eşitlenmiş yöntemle döndürülen sarıcı aracılığıyla yapılması gerekir. " Bu, "kilitsiz çoklu okuyucular" özelliğini oldukça işe yaramaz hale getiriyor gibi görünüyor, o zaman Sözlük'te olduğu gibi Hashtable'a tüm erişimi kilitlemek zorunda kalıyoruz.
RenniePet

16

MSDN Madde " Dictionary<TKey, TValue>sınıfı da aynı özelliğe sahip HashtableA sınıfı. Dictionary<TKey, TValue> (Başka bir özel tip Object) daha iyi bir performansa sahiptir daha Hashtableelemanları için değer türleri için Hashtabletiptedir Object, bu nedenle, ve boks ve saklama oluşabilir tipik kutusu açma ya da msgstr "bir değer türünün alınması".

Bağlantı: http://msdn.microsoft.com/tr-tr/library/4yh14awz(v=vs.90).aspx


11

Her ikisi de etkili bir şekilde aynı sınıftır (sökmeye bakabilirsiniz). HashTable önce oluşturuldu .Net jeneriklere sahipti. Ancak sözlük genel bir sınıftır ve size güçlü yazma avantajları sağlar. Hiçbir zaman HashTable kullanmazdım, çünkü sözlük kullanmanın hiçbir maliyeti yoktur.


8

Bir başka önemli fark Hashtable, iplik güvenli olmasıdır. Hashtablebirden fazla okuyucu / tek yazıcı (MR / SW) iplik güvenliğine sahiptir, Hashtablebu da ONE yazarın birden fazla okuyucu ile birlikte kilitlemeden izin verir. Durumunda Dictionaryorada güvenliğini iplik gerekirse kendi senkronizasyon uygulaması gerektiği hiçbir iplik güvenliğidir.

Daha ayrıntılı olarak açıklamak için:

Hashtable, koleksiyonun çevresinde bir iş parçacığı için güvenli sarmalayıcı döndüren Synchronized özelliği aracılığıyla iş parçacığı güvenliği sağlar. Sargı, toplama veya çıkarma işlemlerinin tümünde tüm koleksiyonu kilitleyerek çalışır. Bu nedenle, koleksiyona erişmeye çalışan her iş parçacığının bir kilidi almasını beklemek gerekir. Bu ölçeklenebilir değildir ve büyük koleksiyonlar için önemli performans düşüşüne neden olabilir. Ayrıca, tasarım yarış koşullarından tamamen korunmuyor.

.NET Framework 2.0 koleksiyon sınıfları gibi List<T>, Dictionary<TKey, TValue>herhangi bir iş parçacığı eşitleme vermeyin vb; eşzamanlı olarak birden çok iş parçacığına öğe eklendiğinde veya kaldırıldığında kullanıcı kodu tüm eşitlemeyi sağlamalıdır. İş parçacığı güvenliğinin yanı sıra tür güvenliğine de ihtiyacınız varsa, .NET Framework'te eşzamanlı koleksiyon sınıflarını kullanın. Burada daha fazla okuma.


3

Sözlükler, genel bir tür olma avantajına sahiptir, bu da boksa ihtiyaç duyulmaması nedeniyle yazıyı güvenli ve biraz daha hızlı hale getirir. Aşağıdaki karşılaştırma tablosu (benzer bir SO soru mesajında ​​bulunan cevaplar kullanılarak oluşturulmuştur ), karma tablolar üzerinde sözlükleri destekleyen diğer nedenleri göstermektedir (ya da tam tersi).


1

Nesneleri her zaman sözlüğe eklendikleri sırayla döndürecek okumayı önemsiyorsanız,

OrderedDictionary - değerlere bir tamsayı dizini üzerinden erişilebilir (öğelerin eklendiği sıraya göre) SortedDictionary - öğeler otomatik olarak sıralanır


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.