| 特性 | Hashtable | Dictionary<TKey,TValue> |
|---|---|---|
| 衝突解決 | 開放定址法(雙重雜湊) | 鏈結串列法(別鏈法) |
| 型別安全 | 非泛型,需裝箱 | 泛型,強型別 |
| 效能 | 較低(裝箱、雙重雜湊) | 較高(無裝箱、快取友好) |
| 執行緒安全 | Hashtable.Synchronized() 提供包裝 | 無內建,需自行鎖定 |
struct bucket
{
object key; // 鍵
object val; // 值
int hash_coll; // 高位元=衝突旗標,低 31 位=雜湊碼
}
hash_coll >= 0:無衝突,低 31 位存 key.GetHashCode() & 0x7FFFFFFF。hash_coll < 0:有衝突(最高位 1),低 31 位仍存雜湊碼。key = buckets(特殊標記)、hash_coll = 0x80000000;無衝突 → 全清 0。
h1 = key.GetHashCode() & 0x7FFFFFFF;
h2 = 1 + ((h1 >> 5) + 1) % (hashsize - 1);
探測位址 i: (h1 + i * h2) % hashsize (i = 0, 1, 2...)
hashsize 為質數(擴容時取近似 2x 的質數),確保 h2 與 hashsize 互質,探測序列覆蓋整個表。α 上限 0.72,超過觸發擴容。h1, h2,初始索引 bn = h1 % hashsize。bn = (bn + h2) % hashsize。key == null(無衝突空位)或 key == buckets(已刪除有衝突空位) → 寫入,count++。KeyEquals → 更新值或拋例外(Add 模式)。hash_coll < 0) → 將該位置 hash_coll 最高位置 1。count >= loadsize → expand()(rehash 到新質數大小陣列)。h1, h2、初始索引。hash_coll >= 0(無衝突) → 結束回傳 null;hashsize → 結束回傳 null。hash_coll < 0):hash_coll &= 0x80000000、key = buckets、val = null。key = val = null、hash_coll = 0。count--。
newSize = HashHelpers.GetPrime(buckets.Length * 2);
newBuckets = new bucket[newSize];
foreach (oldBucket in buckets)
if (oldBucket.key != null && oldBucket.key != buckets)
putEntry(newBuckets, oldBucket.key, oldBucket.val, oldBucket.hash_coll & 0x7FFFFFFF);
buckets = newBuckets;
loadsize = (int)(loadFactor * newSize);
public class SimpleHashtable
{
struct Entry { public object Key, Value; public int HashColl; }
Entry[] buckets; int count, loadSize; float loadFactor = 0.72f;
public SimpleHashtable(int capacity = 11)
{
int size = capacity > 11 ? GetPrime(capacity) : 11;
buckets = new Entry[size];
loadSize = (int)(loadFactor * size);
}
public void Add(object key, object value) => Insert(key, value, true);
public object this[object key] { get => Find(key); set => Insert(key, value, false); }
private void Insert(object key, object value, bool add)
{
if (count >= loadSize) Expand();
uint h1 = (uint)(key.GetHashCode() & 0x7FFFFFFF);
uint h2 = 1 + ((h1 >> 5) + 1) % (uint)(buckets.Length - 1);
int bn = (int)(h1 % (uint)buckets.Length);
int emptySlot = -1, ntry = 0;
while (true)
{
ref Entry e = ref buckets[bn];
if (e.Key == null)
{
if (emptySlot != -1) bn = emptySlot;
e.Key = key; e.Value = value; e.HashColl = (int)h1; count++; return;
}
if (e.Key == buckets) { emptySlot = bn; } // 記錄已刪除衝突位
if ((e.HashColl & 0x7FFFFFFF) == h1 && key.Equals(e.Key))
{
if (add) throw new ArgumentException("Key exists");
e.Value = value; return;
}
if (emptySlot == -1 && e.HashColl >= 0) e.HashColl |= unchecked((int)0x80000000);
bn = (int)((bn + h2) % (uint)buckets.Length);
if (++ntry >= buckets.Length) throw new Exception("Full");
}
}
// Find, Remove, Expand, GetPrime 略...
}
Hashtable 以開放定址法 + 雙重雜湊實作,透過 hash_coll 高位元標記衝突、特殊標記處理刪除,設計精巧但受限於裝箱與探測機制,現代開發首選 Dictionary<TKey,TValue>。