我想更好地瞭解散列集的內部如何HashSet<T>
做的工作,爲什麼他們表演。我發現了以下文章,用桶列表http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/實現了一個簡單的例子。據我瞭解這篇文章(我也認爲這種方式之前),桶列表本身分組在每個桶中的一定數量的元素。一個桶由散列碼錶示,即由元素上調用的GetHashCode
表示。我認爲更好的表現是基於桶比元素少的事實。GetHashCode和Buckets
現在我已經寫了以下幼稚的測試代碼:
public class CustomHashCode
{
public int Id { get; set; }
public override int GetHashCode()
{
//return Id.GetHashCode(); // Way better performance
return Id % 40; // Bad performance! But why?
}
public override bool Equals(object obj)
{
return ((CustomHashCode) obj).Id == Id;
}
}
這裏探查:
public static void TestNoCustomHashCode(int iterations)
{
var hashSet = new HashSet<NoCustomHashCode>();
for (int j = 0; j < iterations; j++)
{
hashSet.Add(new NoCustomHashCode() { Id = j });
}
var chc = hashSet.First();
var stopwatch = new Stopwatch();
stopwatch.Start();
for (int j = 0; j < iterations; j++)
{
hashSet.Contains(chc);
}
stopwatch.Stop();
Console.WriteLine(string.Format("Elapsed time (ms): {0}", stopwatch.ElapsedMilliseconds));
}
我天真的想法是:讓我們降低桶的量(用一個簡單的模) ,這應該會提高性能。但它是可怕的(在我的系統上,需要4秒鐘,50000次迭代)。我還想過,如果我簡單地將Id作爲散列碼返回,性能應該很差,因爲我最終會得到50000個存儲桶。但情況正好相反,我想我只是簡單地產生了所謂的碰撞音,而不是改善任何事情。但是,再次,桶列表如何工作?
爲什麼你覺得桶數目少好?每個桶最好有一個入口,這就是爲什麼'HashSet'等以你的哈希碼爲模的容量。如果你有5萬項,但只有50桶,每個操作需要通過1000個項目的鏈接列表順序搜索=>慢 –
CodesInChaos
理想的散列碼應該是一個快捷方式到平等不是有些不太具體的「鬥」標識。 「桶」中的所有項目應該相等。 – Jodrell
對 - 我認爲我錯誤地認爲在桶列表中查找本身也很昂貴,這一定是無稽之談。 – sl3dg3