2009-10-26 24 views
8

.NET'te, int capacity numaralı parametreleri içeren Dictionary<TKey, TValue> için bir yapıcı var. Bu, List<T>, Queue<T> ve Stack<T> gibi diğer birçok koleksiyonla aynıdır; ayrıca, the MSDN documentation:Neden Dictionary.TrimExcess() var mı?

'a göre Bir Sözlükün kapasitesi, yeniden boyutlandırmadan önce Sözlüğe eklenebilecek öğelerin sayısıdır. Öğeler bir Sözlüğe eklendikçe, iç diziyi yeniden tahsis ederek kapasite gerektiği gibi otomatik olarak artırılır.

Bu

özelliği hemen hemen bana bu koleksiyonları yana vb List<T> gibi diğer koleksiyonları ile aynı sesler otomatik boyutlandırma gerekli ve bunların çoğu bir özelliği, gerekenden daha büyük bir kapasiteye sahip olması dolayısıyla muhtemel davranış TrimExcess yöntemi. Bu, koleksiyona bir defada bilinmeyen sayıda öğe eklediğiniz ve bu sayede ek öğeler eklemeyeceğiniz anlamına gelir.

Dictionary<TKey, TValue> neden bu kadar değil TrimExcess yöntemi?

(Yasal Uyarı: tepkisi "varsayılan olarak bulunmaz özellikler" ile oldukça aşina değilim; ben Dictionary için TrimExcess mantıklı, ya da neden bunu değil belirli bir nedeni var mı, çoğunlukla sadece merak ediyordum List gibi basit koleksiyonları için uygulanması daha çok daha zor olurdu)

+0

yana ' HashSet' bir 'TrimExcess' yöntemine sahiptir ve ayrıca HashTable ile dahili olarak çalışır, 'Dictionary' için' TrimExcess 'uygulamasının teknik bir nedeni yoktur. Hatta belgelerde 'HashSet'in değerler olmadan 'Sözlük' olduğunu söylerler. – Kjara

cevap

3

Her Sözlük için bir karma tablosu olarak uygulanır. Aşırı kırpmış olsaydınız, etkin olarak rastgele sıralanmış bir liste olacak şekilde O (1) arama sürelerine yakın bir şekilde sağlanan bir algoritma bulmak zorunda kalacaktınız.

+4

Net değilse O (1) araması TrimExess ile ne yapar? O (n) 'de HashSet.TrimExess. – Paparazzi

4

Ben bu durumda kapasite argümanı karma işlevi yanı sıra bölüm sayısını tanımlamak yardımcı olduğunu tahmin ediyorum.; Seyrek bir veri koleksiyonunu yeniden boyutlandırmak/kırpmak, kalan tüm saklanan kalemlerin yeniden hesaplanmasını gerektirir.

+1

Aslında, GetHashCode() 'aracılığıyla Key nesnesinin kod kodunu kullanır ve en anlamlı biti kaldırırlar. Daha sonra, dizinin içindeki bir yerde, uzunluk% karma değerinin geri kalanıyla (ücretsiz bir tane bulunana kadar) saklarlar. Tabii ki, karma kodların hesaplanması anahtar-sınıf bağımlıdır. – Abel

+1

Daha fazla teknik ayrıntıda Sözlük, "bucket [key.getHashCode()% buckets.Length] = value" kullanarak bir öğeyi yerleştirmek için hangi kovanı seçer. Kepçe listesinin uzunluğunun değiştirilmesi, tüm değerlerin yeni kepçelere taşınmasını gerektirir. – Juliet

+0

@Juliet: neredeyse. Gerektiğinde kova yeniden boyutlandırılır ve tüm girdi listesi süreç içinde kopyalanır ve indeksler yeniden hesaplanır ve böylece nesneler yeniden konumlandırılır. – Abel

5

Bu kısmen bir tahmindir: Sözlük "hash" tablosu olarak "sipariş edilir". Rezerve edilen kapasite, Sözlüğünüzün üzerinde bir grup boş hafıza adresi değildir. Bunun yerine, Sözlük boyunca boş odadan oluşur. Bu, ekleme/taşıma/çıkarma vb. Çok verimli hale getirmek için yapılır. Sözlük için bir TrimExcess yöntemine sahip olsaydınız, tüm Sözlük, öğeler arasında herhangi bir boşluk olmadan her şeyi yeni bir konuma kopyalamak zorunda kalırdı.

Aslında: boşluklar aksi karma tablo yararı kalmalıdır kırpma, ( TrimExcess) geçersiz hale gelir, eğer uygulanırsa, yalnızca iç ValueCollection Döşeme gerekir.

Güncelleme: genişletilmiş ve benim kötü seçilmiş kelimeler
Güncelleme değiştirdi:the BCL team says TrimExcess for Dictionaries "could be useful".
Güncelleştirme: özellik isteği düzeltilemedi: "Maalesef, .NET'in bir sonraki sürümü için bunu alamayız, bu yüzden bunu Fix't Fix olarak çözüyorum ."

+0

Sözlük sipariş edilmiyor - bu bir karma tablosu olarak uygulanmaktadır. Sipariş edilen eşdeğer SortedDictionary. – user200783

+0

Biliyorum, bu şekilde sipariş edilmiyor, bir karma olarak sipariş ediliyor. Üzgünüz, – Abel

1

Aslında Microsoft'tan TrimExcess uygulamasını isteyen kişiydim. Ben zaten sözlüklerle ilgilenen birden fazla makale sundum ve her durumda TrimExcess'i uyguladım.Aslında, kovalar çok küçük olduğunda, Yeniden boyutlandırma, kovaların boyutunu arttırırken veya azalırken kullanılabilir. Bu makalede bulunabilir http://www.codeproject.com/Articles/761040/A-NET-like-Dictionary-in-Cplusplus

başka uygulama (.NET): Ben sadece başka makale yayınladı

Bugün, TrimExcess destekleyen bir C++ bir sözlük uygulamasıdır http://www.codeproject.com/Articles/548406/Dictionary-plus-Locking-versus-ConcurrentDictionar