.NET源码中的HashSet<T>
来源:互联网 发布:个人网盘网站源码 编辑:程序博客网 时间:2024/05/23 12:55
HashSet<T>用来存储一组无指定顺序的对象的集合,特点是高性能。
内部数据结构定义如下:
public class HashSet<T> : ISerializable, IDeserializationCallback, ISet<T>, ICollection<T>, IEnumerable<T>, IEnumerable { private int[] m_buckets; private HashSet<T>.Slot[] m_slots; private int m_count; private int m_lastIndex; private int m_freeList; private const int Lower31BitMask = 2147483647; private const int StackAllocThreshold = 100; private const int ShrinkThreshold = 3;
其中Slot结构体的定义如下:
internal struct Slot { internal int hashCode; internal T value; internal int next; }
添加新值的实现:
private bool AddIfNotPresent(T value) { if (this.m_buckets == null) this.Initialize(0); int hashCode = this.InternalGetHashCode(value); int index1 = hashCode % this.m_buckets.Length; int num = 0; 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)) { this.m_comparer = (IEqualityComparer<T>) HashHelpers.GetRandomizedEqualityComparer((object) this.m_comparer); this.SetCapacity(this.m_buckets.Length, true); } return true; }
其中Initialize()的实现如下:通过HashHelpers类的静态函数GetPrime()函数取一个素数,作为bucket数组和slot数组的初始大小。
private void Initialize(int capacity) { int prime = HashHelpers.GetPrime(capacity); this.m_buckets = new int[prime]; this.m_slots = new HashSet<T>.Slot[prime]; }
GetPrime()的实现如下:
public static int GetPrime(int min) { if (min < 0) throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow")); for (int index = 0; index < HashHelpers.primes.Length; ++index) { int num = HashHelpers.primes[index]; if (num >= min) return num; } int candidate = min | 1; while (candidate < int.MaxValue) { if (HashHelpers.IsPrime(candidate) && (candidate - 1) % 101 != 0) return candidate; candidate += 2; } return min; }
HashHelpers内置了一组素数:
public static readonly int[] primes = new int[72] { 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 };
而判断一个数是否为素数的函数如下:
public static bool IsPrime(int candidate) { if ((candidate & 1) == 0) return candidate == 2; int num1 = (int) Math.Sqrt((double) candidate); int num2 = 3; while (num2 <= num1) { if (candidate % num2 == 0) return false; num2 += 2; } return true; }
InternalGetHashCode的实现是根据不同类型调用相关的GetHashCode函数与int.MaxValue做&运算,参考.NET中基本数据类型的GetHashCode
private int InternalGetHashCode(T item) { if ((object) item == null) return 0; else return this.m_comparer.GetHashCode(item) & int.MaxValue; }
当达到容限时,需要扩容:
private void IncreaseCapacity() { int newSize = HashHelpers.ExpandPrime(this.m_count); if (newSize <= this.m_count) throw new ArgumentException(SR.GetString("Arg_HSCapacityOverflow")); this.SetCapacity(newSize, false); } private void SetCapacity(int newSize, bool forceNewHashCodes) { HashSet<T>.Slot[] slotArray = new HashSet<T>.Slot[newSize]; if (this.m_slots != null) Array.Copy((Array) this.m_slots, 0, (Array) slotArray, 0, this.m_lastIndex); if (forceNewHashCodes) { for (int index = 0; index < this.m_lastIndex; ++index) { if (slotArray[index].hashCode != -1) slotArray[index].hashCode = this.InternalGetHashCode(slotArray[index].value); } } int[] numArray = new int[newSize]; for (int index1 = 0; index1 < this.m_lastIndex; ++index1) { int index2 = slotArray[index1].hashCode % newSize; slotArray[index1].next = numArray[index2] - 1; numArray[index2] = index1 + 1; } this.m_slots = slotArray; this.m_buckets = numArray; }
查找某个数据是否存在于hashset中的实现如下:
public bool Contains(T item) { if (this.m_buckets != null) { int hashCode = this.InternalGetHashCode(item); 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; }
删除某个数据的实现:
public bool Remove(T item) { if (this.m_buckets != null) { int hashCode = this.InternalGetHashCode(item); int index1 = hashCode % this.m_buckets.Length; int index2 = -1; 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) this.m_buckets[index1] = this.m_slots[index3].next + 1; else 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; return true; } else index2 = index3; } } return false; }
导出到数组的实现:
public void CopyTo(T[] array, int arrayIndex, int count) { if (array == null) throw new ArgumentNullException("array"); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex", SR.GetString("ArgumentOutOfRange_NeedNonNegNum")); if (count < 0) throw new ArgumentOutOfRangeException("count", SR.GetString("ArgumentOutOfRange_NeedNonNegNum")); if (arrayIndex > array.Length || count > array.Length - arrayIndex) throw new ArgumentException(SR.GetString("Arg_ArrayPlusOffTooSmall")); int num = 0; for (int index = 0; index < this.m_lastIndex && num < count; ++index) { if (this.m_slots[index].hashCode >= 0) { array[arrayIndex + num] = this.m_slots[index].value; ++num; } } }
以上
0 0
- .NET源码中的HashSet<T>
- HashSet<T> 源码解析
- .net集合类的研究--哈希表(二)--HashSet<T>
- .net集合类的研究--哈希表(二)--HashSet<T>
- .net集合类的研究--哈希表-HashSet<T>
- HashSet源码
- HashSet源码
- HashSet<T>类
- java 中的集合(九) HashSet源码分析
- .NET源码中的栈
- .NET源码中的队列
- .NET源码中的SortedSet
- JDK8中的Comparable<T>接口源码分析
- C#解惑:HashSet<T>类
- HashTable & HashSet 源码分析
- hashset 源码解析
- HashSet源码分析
- HashSet源码分析
- 一个更好的Post process结构,三角形代替四边形。
- memcache控制高并发问题
- 【Unity3D自学记录】NGUI之判断鼠标是否在UI界面上
- CSS 浏览器私有前缀
- 【转】【STL】next_permutation的原理和使用
- .NET源码中的HashSet<T>
- Cocos2d-x中2.x和3.x的粒子系统的比较
- C++ OOP
- android 图片裁剪
- HDU 1546 Idiomatic Phrases Game
- Hibernate学习之对象持久化
- java集合大家族 分类
- 利用Server Header tool 检查404 错误返回状态
- 数字视频基础(一)