1.Dictionary<TKey,TValue> 主要对象 Entry[]
private Dictionary<TKey, TValue>.Entry[] entries;
using System;
// Token: 0x02000BA6 RID: 2982
private struct Entry
{
// Token: 0x040034EC RID: 13548
public int hashCode;
// Token: 0x040034ED RID: 13549
public int next;
// Token: 0x040034EE RID: 13550
public TKey key;
// Token: 0x040034EF RID: 13551
public TValue value;
}
2.内存管理,HashHelpers.primes 一组已定义的集合大小数组。
public static int GetPrime(int min)
{
if (min < 0)
{
throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow"));
}
for (int i = 0; i < HashHelpers.primes.Length; i++)
{
int num = HashHelpers.primes[i];
if (num >= min)
{
return num;
}
}
for (int j = min | 1; j < 2147483647; j += 2)
{
if (HashHelpers.IsPrime(j) && (j - 1) % 101 != 0)
{
return j;
}
}
return min;
}
3.buckets、Entry(集合)数组的初始化 (buckets哈希表)、(capacity容量)
// System.Collections.Generic.Dictionary<TKey, TValue>
// Token: 0x06003921 RID: 14625 RVA: 0x000D97B8 File Offset: 0x000D79B8
private void Initialize(int capacity)
{
int prime = HashHelpers.GetPrime(capacity);
this.buckets = new int[prime];
for (int i = 0; i < this.buckets.Length; i++)
{
this.buckets[i] = -1;
}
this.entries = new Dictionary<TKey, TValue>.Entry[prime];
this.freeList = -1;
}
4.IDictionary<Tkey,Tvalue>接口
using System;
namespace System.Collections.Generic
{
// Token: 0x020004A5 RID: 1189
[__DynamicallyInvokable]
public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
{
// Token: 0x170008CC RID: 2252
[__DynamicallyInvokable]
TValue this[TKey key]
{
[__DynamicallyInvokable]
get;
[__DynamicallyInvokable]
set;
}
// Token: 0x170008CD RID: 2253
// (get) Token: 0x06003998 RID: 14744
[__DynamicallyInvokable]
ICollection<TKey> Keys { [__DynamicallyInvokable] get; }
// Token: 0x170008CE RID: 2254
// (get) Token: 0x06003999 RID: 14745
[__DynamicallyInvokable]
ICollection<TValue> Values { [__DynamicallyInvokable] get; }
// Token: 0x0600399A RID: 14746
[__DynamicallyInvokable]
bool ContainsKey(TKey key);
// Token: 0x0600399B RID: 14747
[__DynamicallyInvokable]
void Add(TKey key, TValue value);
// Token: 0x0600399C RID: 14748
[__DynamicallyInvokable]
bool Remove(TKey key);
// Token: 0x0600399D RID: 14749
[__DynamicallyInvokable]
bool TryGetValue(TKey key, out TValue value);
}
}
5.函数实现添加
// System.Collections.Generic.Dictionary<TKey, TValue>
// Token: 0x06003922 RID: 14626 RVA: 0x000D9808 File Offset: 0x000D7A08
private void Insert(TKey key, TValue value, bool add)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (this.buckets == null)
{
this.Initialize(0);
}
int num = this.comparer.GetHashCode(key) & int.MaxValue;
int num2 = num % this.buckets.Length;
int num3 = 0;
for (int i = this.buckets[num2]; i >= 0; i = this.entries[i].next)
{
if (this.entries[i].hashCode == num && this.comparer.Equals(this.entries[i].key, key))
{
if (add)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
this.entries[i].value = value;
this.version++;
return;
}
num3++;
}
int num4;
if (this.freeCount > 0)
{
num4 = this.freeList;
this.freeList = this.entries[num4].next;
this.freeCount--;
}
else
{
if (this.count == this.entries.Length)
{
this.Resize();
num2 = num % this.buckets.Length;
}
num4 = this.count;
this.count++;
}
this.entries[num4].hashCode = num;
this.entries[num4].next = this.buckets[num2];
this.entries[num4].key = key;
this.entries[num4].value = value;
this.buckets[num2] = num4;
this.version++;
if (num3 > 100 && HashHelpers.IsWellKnownEqualityComparer(this.comparer))
{
this.comparer = (IEqualityComparer<TKey>)HashHelpers.GetRandomizedEqualityComparer(this.comparer);
this.Resize(this.entries.Length, true);
}
}
哈希表,这个算法太厉害了,很佩服微软大神,先说哈希表这个机制的作用
1.查询速度会非常快,数据的多少不影响查询速度
我们分2种情况来讨论这个
1.一张表记录数据在集合的位置的表,表是素数个数,方便数据地址分配这个表中(现在表的大小3)
2.集合
1.不冲突
key的GethashCode()mod表的大小,在这个表余数是0,在表0的位置中没有放内存为-1,判断是否大于0,直接放数据地址,查询的时候,余数0,直接取表的数据地址,比对哈希表的值,再比对对象是是否一致。
2.冲突
同样余数0,在表0的位置存数据地址,发现表0地址大于0等于0,那问题就来了,说明已经存数据地址,怎么办,微软大神,用链接法,继续存数据地址,但是把之前的地址复制给数据中next,这时候查询是从表中取出的地址与key的哈希表对比值,如果相等,就比较key的值。
其他的接口下次补充