HashSet表示值的集合。
源码中,获取哈希吗的算法:
private int InternalGetHashCode(T item)
{
if (item == null)
{
return 0;
}
return _comparer.GetHashCode(item) & Lower31BitMask;
}
// store lower 31 bits of hash code
private const int Lower31BitMask = 0x7FFFFFFF;
再看一个内部封装的,加入一个元素到集合中,
//Returns true if added and false if already present
private bool AddIfNotPresent(T value)
{
if (_buckets == null)
{
Initialize(0);
}
int hashCode = InternalGetHashCode(value);
int bucket = hashCode % _buckets.Length;
for (int i = _buckets[bucket] - 1; i >= 0; i = _slots[i].next)
{
if (_slots[i].hashCode == hashCode && _comparer.Equals(_slots[i].value, value))
{
return false;
}
}
int index;
if (_freeList >= 0)
{
index = _freeList;
_freeList = _slots[index].next;
}
else
{
if (_lastIndex == _slots.Length)
{
IncreaseCapacity();
// this will change during resize
bucket = hashCode % _buckets.Length;
}
index = _lastIndex;
_lastIndex++;
}
_slots[index].hashCode = hashCode;
_slots[index].value = value;
_slots[index].next = _buckets[bucket] - 1;
_buckets[bucket] = index + 1;
_count++;
_version++;
return true;
}
看了以上封装的这个方法后,我们再看下一个公开的API,
/// <summary>
/// Add item to this hashset. This is the explicit implementation of the ICollection<T>
/// interface. The other Add method returns bool indicating whether item was added.
/// </summary>
/// <param name="item">item to add</param>
void ICollection<T>.Add(T item)
{
AddIfNotPresent(item);
}
再看一个完成添加元素到集合的API,
/// <summary>
/// Add item to this HashSet. Returns bool indicating whether item was added (won't be
/// added if already present)
/// </summary>
/// <param name="item"></param>
/// <returns>true if added, false if already present</returns>
public bool Add(T item)
{
return AddIfNotPresent(item);
}
继续分析一个合并两个集合的API,它用到了内部私有的添加元素到集合的方法,
/// <summary>
/// Take the union of this HashSet with other. Modifies this set.
///
/// Implementation note: GetSuggestedCapacity (to increase capacity in advance avoiding
/// multiple resizes ended up not being useful in practice; quickly gets to the
/// point where it's a wasteful check.
/// </summary>
/// <param name="other">enumerable with items to add</param>
public void UnionWith(IEnumerable<T> other)
{
if (other == null)
{
throw new ArgumentNullException(nameof(other));
}
Contract.EndContractBlock();
foreach (T item in other)
{
AddIfNotPresent(item);
}
}
总结,微软在实现HashSet,添加某个元素到集合时,内部私有实现了一个AddIfNotPresent方法,在它内部用到了InternalGetHashCode算法获取添加元素的哈希值。暴露的这些添加元素的API都是调用了AddIfNotPresent方法。这便是添加元素到哈希表的实现细节。
作者:daigualu 发表于2017/3/14 23:02:42 原文链接
阅读:72 评论:0 查看评论