/// <summary> /// Adds value to HashSet if not contained already /// Returns true if added and false if already present /// </summary> /// <param name="value">value to find</param> /// <returns></returns> private bool AddIfNotPresent(T value) { if (m_buckets == null) { Initialize(0); } int hashCode = InternalGetHashCode(value); int bucket = hashCode % m_buckets.Length; #if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE int collisionCount = 0; #endif for (int i = m_buckets[hashCode % m_buckets.Length] - 1; i >= 0; i = m_slots[i].next) { if (m_slots[i].hashCode == hashCode && m_comparer.Equals(m_slots[i].value, value)) { return(false); } #if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE collisionCount++; #endif } int index; if (m_freeList >= 0) { index = m_freeList; m_freeList = m_slots[index].next; } else { if (m_lastIndex == m_slots.Length) { IncreaseCapacity(); // this will change during resize bucket = hashCode % m_buckets.Length; } index = m_lastIndex; m_lastIndex++; } m_slots[index].hashCode = hashCode; m_slots[index].value = value; m_slots[index].next = m_buckets[bucket] - 1; m_buckets[bucket] = index + 1; m_count++; m_version++; #if FEATURE_RANDOMIZED_STRING_HASHING && !FEATURE_NETCORE if (collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(m_comparer)) { m_comparer = (IEqualityComparer <T>)HashHelpers.GetRandomizedEqualityComparer(m_comparer); SetCapacity(m_buckets.Length, true); } #endif // FEATURE_RANDOMIZED_STRING_HASHING return(true); }
private bool AddIfNotPresent(T value) { if (_buckets == null) { Initialize(0); } int hashCode = InternalGetHashCode(value); int bucket = hashCode % _buckets.Length; #if FEATURE_RANDOMIZED_STRING_HASHING int collisionCount = 0; #endif 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); } #if FEATURE_RANDOMIZED_STRING_HASHING collisionCount++; #endif } int index; if (_freeList >= 0) { index = _freeList; _freeList = _slots[index].next; } else { if (_lastIndex == _slots.Length) { IncreaseCapacity(); 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++; #if FEATURE_RANDOMIZED_STRING_HASHING if (collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_comparer)) { _comparer = (IEqualityComparer <T>)HashHelpers.GetRandomizedEqualityComparer(_comparer); SetCapacity(_buckets.Length, true); } #endif return(true); }
private void Insert(TKey key, TValue value, bool add) { if (key == null) { throw new KeyNotFoundException(nameof(key)); } if (buckets == null) { Initialize(0); } int hashCode = Comparer.GetHashCode(key) & 0x7FFFFFFF; int targetBucket = hashCode % buckets.Length; for (int i = buckets[targetBucket]; i >= 0; i = entries[i].Next) { if (entries[i].HashCode == hashCode && Comparer.Equals(entries[i].Key, key)) { if (add) { throw new ArgumentException("Adding Duplicate"); } entries[i].Value = value; version++; return; } } int index; if (freeCount > 0) { index = freeList; freeList = entries[index].Next; freeCount--; } else { if (count == entries.Length) { Resize(); targetBucket = hashCode % buckets.Length; } index = count; count++; } entries[index].HashCode = hashCode; entries[index].Next = buckets[targetBucket]; entries[index].Key = key; entries[index].Value = value; buckets[targetBucket] = index; version++; #if FEATURE_RANDOMIZED_STRING_HASHING #if FEATURE_CORECLR // In case we hit the collision threshold we'll need to switch to the comparer which is using randomized string hashing // in this case will be EqualityComparer<string>.Default. // Note, randomized string hashing is turned on by default on coreclr so EqualityComparer<string>.Default will // be using randomized string hashing if (collisionCount > HashHelpers.HashCollisionThreshold && comparer == NonRandomizedStringEqualityComparer.Default) { comparer = (IEqualityComparer <TKey>)EqualityComparer <string> .Default; Resize(entries.Length, true); } #else if (collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(comparer)) { comparer = (IEqualityComparer <TKey>)HashHelpers.GetRandomizedEqualityComparer(comparer); Resize(entries.Length, true); } #endif // FEATURE_CORECLR #endif }
private void Insert(TKey key, TValue value, bool add) { if (key == null) { throw new ArgumentNullException(); } if (buckets == null) { Initialize(0); } int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; //将HashCode的返回值转化为数组索引 int targetBucket = hashCode % buckets.Length; // 处理hash碰撞冲突:如果转换出的targetBucket大于等于0,判断buckets数组中有没有相等的,如果相等,需要处理冲突 int collisionCount = 0; // 哈希碰撞 for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next) { //如果转换的hash值与之前已经添加的hash值相等,同时插入的key与之前的相同,处理冲突,key是唯一的,不能重复 if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) { if (add) { throw new Exception("Dictionary add duplicate key" + key.ToString()); } // 覆盖更新值 entries[i].value = value; version++; return; } collisionCount++; } int index; // 如果空链表的长度大于0,FreeList链表不为空,字典会优先把新增元素添加到FreeList链表所指向的位置 if (freeCount > 0) { index = freeList; // freeList 找到链表的上一个节点 freeList = entries[index].next; freeCount--; } else { //如果数组已满,需扩容 if (count == entries.Length) { Resize(); targetBucket = hashCode % buckets.Length; } index = count; count++; } entries[index].hashCode = hashCode; //新增元素的next指向上一个元素的索引 entries[index].next = buckets[targetBucket]; entries[index].key = key; entries[index].value = value; //记录新增元素的索引 buckets[targetBucket] = index; version++; //如果碰撞次数(单链表长度)大于设置的最大碰撞阈值,需要扩容 if (collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(comparer)) { //comparer = (IEqualityComparer<TKey>)HashHelpers.GetRandomizedEqualityComparer(comparer); Resize(entries.Length, true); } }
private void Insert(TKey key, TValue value, bool add) { if (key == null) { ThrowHelper("ExceptionArgument.key"); } if (buckets == null) { Initialize(0); } int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; int targetBucket = hashCode % buckets.Length; #if FEATURE_RANDOMIZED_STRING_HASHING int collisionCount = 0; #endif for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next) { if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) { if (add) { ThrowHelper("Argument_AddingDuplicate"); } entries[i].value = value; version++; return; } #if FEATURE_RANDOMIZED_STRING_HASHING collisionCount++; #endif } int index; if (freeCount > 0) { index = freeList; freeList = entries[index].next; freeCount--; } else { if (count == entries.Length) { Resize(); targetBucket = hashCode % buckets.Length; } index = count; count++; } entries[index].hashCode = hashCode; entries[index].next = buckets[targetBucket]; entries[index].key = key; entries[index].value = value; buckets[targetBucket] = index; version++; #if FEATURE_RANDOMIZED_STRING_HASHING if (collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(comparer)) { comparer = (IEqualityComparer <TKey>)HashHelpers.GetRandomizedEqualityComparer(comparer); Resize(entries.Length, true); } #endif }