所在框架版本:.Net Framework 4.0.30319
1.部分变量
private const int Lower31BitMask = 2147483647;
private const int StackAllocThreshold = 100;
private const int ShrinkThreshold = 3;
private const string CapacityName = "Capacity";
private const string ElementsName = "Elements";
private const string ComparerName = "Comparer";
private const string VersionName = "Version";
private int[] m_buckets; //桶数组
private HashSet<T>.Slot[] m_slots; //元素数组
private int m_count;
private int m_lastIndex;
private int m_freeList; //空闲元素数组下标
private IEqualityComparer<T> m_comparer;
private int m_version;
private SerializationInfo m_siInfo;
2.构造函数
public HashSet(int capacity, IEqualityComparer<T> comparer) //参数:容量,比较器
: this(comparer)
{
if (capacity < 0)
throw new ArgumentOutOfRangeException(nameof (capacity));
if (capacity <= 0)
return;
this.Initialize(capacity);
}
3.初始化
private void Initialize(int capacity)
{
int prime = HashHelpers.GetPrime(capacity); //获得大于容量的最小质数
this.m_buckets = new int[prime]; //初始化桶数组
this.m_slots = new HashSet<T>.Slot[prime]; //初始化元素数组
}
4.添加
public bool Add(T item) => this.AddIfNotPresent(item);
private bool AddIfNotPresent(T value)
{
if (this.m_buckets == null) //如果桶数组为空
this.Initialize(0); //重新初始化
int hashCode = this.InternalGetHashCode(value); //通过值获取hash值
int index1 = hashCode % this.m_buckets.Length; //获得桶下标
int num = 0; //hash碰撞次数
for (int index2 = this.m_buckets[hashCode % this.m_buckets.Length] - 1; index2 >= 0; index2 = this.m_slots[index2].next) //遍历元素链
{
if (this.m_slots[index2].hashCode == hashCode && this.m_comparer.Equals(this.m_slots[index2].value, value)) //如果某个元素已经存在
return false;
++num;
}
int index3;
if (this.m_freeList >= 0) //如果存在空闲位置
{
index3 = this.m_freeList;
this.m_freeList = this.m_slots[index3].next;
}
else
{
if (this.m_lastIndex == this.m_slots.Length) //满了
{
this.IncreaseCapacity(); //扩容
index1 = hashCode % this.m_buckets.Length; //重新确定桶下标
}
index3 = this.m_lastIndex;
++this.m_lastIndex;
}
//元素数组赋值
this.m_slots[index3].hashCode = hashCode;
this.m_slots[index3].value = value;
this.m_slots[index3].next = this.m_buckets[index1] - 1;
this.m_buckets[index1] = index3 + 1;
++this.m_count;
++this.m_version; //版本号更新
if (num > 100 && HashHelpers.IsWellKnownEqualityComparer((object) this.m_comparer)) // 如果碰撞次数大于设置的最大碰撞次数,那么触发Hash碰撞扩容
{
this.m_comparer = (IEqualityComparer<T>) HashHelpers.GetRandomizedEqualityComparer((object) this.m_comparer);
this.SetCapacity(this.m_buckets.Length, true);
}
return true;
}
5.查找
public bool Contains(T item)
{
if (this.m_buckets != null)
{
int hashCode = this.InternalGetHashCode(item); //获得值对应的hash值
for (int index = this.m_buckets[hashCode % this.m_buckets.Length] - 1; index >= 0; index = this.m_slots[index].next) //遍历元素链
{
if (this.m_slots[index].hashCode == hashCode && this.m_comparer.Equals(this.m_slots[index].value, item))
return true;
}
}
return false;
}
6.移除
public bool Remove(T item)
{
if (this.m_buckets != null)
{
int hashCode = this.InternalGetHashCode(item); //获得hash值
int index1 = hashCode % this.m_buckets.Length; //获得桶数组下标
int index2 = -1; // 用于确定是否当前entries链的第一个元素
for (int index3 = this.m_buckets[index1] - 1; index3 >= 0; index3 = this.m_slots[index3].next) //遍历元素链
{
if (this.m_slots[index3].hashCode == hashCode && this.m_comparer.Equals(this.m_slots[index3].value, item))
{
if (index2 < 0) //如果要移除的是第一个元素,则对应桶存储当前元素的Next元素下标
this.m_buckets[index1] = this.m_slots[index3].next + 1;
else //不是第一个,需要将上一个元素的Next指向当前元素的Next,相当于越过了当前元素
this.m_slots[index2].next = this.m_slots[index3].next;
//元素数组数据重置
this.m_slots[index3].hashCode = -1;
this.m_slots[index3].value = default (T);
this.m_slots[index3].next = this.m_freeList;
--this.m_count;
++this.m_version; //版本号更新
if (this.m_count == 0)
{
this.m_lastIndex = 0;
this.m_freeList = -1;
}
else
this.m_freeList = index3; //freeList等于当前的元素数组的位置,下一次添加元素会优先添加到该位置
return true;
}
index2 = index3; //不断在这个链表上往后移动
}
}
return false;
}