private void Resize() { Resize(HashHelpers.ExpandPrime(count), false); }
//-替换 && 添加 //-查找规则:0.当有备用数组元素时,取备用数组 1.当数组长度已满时,扩容,取第一个 2.当数组长度未满时,取第一个 private void Insert(TKey key, TValue value, bool add) { if (key == null) { ThrowHelper.ThrowArgumentNullException(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.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); } entries[i].value = value; version++; return; } #if FEATURE_RANDOMIZED_STRING_HASHING collisionCount++; #endif } int headIndex; if (freeCount > 0) { headIndex = freeList; freeList = entries[headIndex].next; freeCount--; } //- Count = count - freeCount; else //-当前没有多余Count,扩容,取最后一位 { if (count == entries.Length) { Resize(); targetBucket = hashCode % buckets.Length; } headIndex = count; count++; } //-遍历是按照他的添加顺序来决定的 entries[headIndex].hashCode = hashCode; //-添加链表 var beforeHandIndex = buckets[targetBucket]; buckets[targetBucket] = headIndex; entries[headIndex].key = key; entries[headIndex].value = value; entries[headIndex].next = beforeHandIndex; //-buckets[targetBucket]永远只存第一个元素,把当前index放在buckets的第一位 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 }
public RandomizedObjectEqualityComparer() { _entropy = HashHelpers.GetEntropy(); }
private void Insert(TKey key, TValue value, bool add) { if (key == null) { throw new ArgumentNullException(nameof(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) { throw new ArgumentException(SR.Format(SR.Argument_AddingDuplicate, key)); } 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 }
public RandomizedStringEqualityComparer() { _entropy = HashHelpers.GetEntropy(); }