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.ThrowAddingDuplicateWithKeyArgumentException(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 // 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); } #endif }
//-替换 && 添加 //-查找规则: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 }
void ICollection.CopyTo(Array array, int index) { if (array == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } if (array.Rank != 1) { ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); } if (array.GetLowerBound(0) != 0) { ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); } if (index < 0 || index > array.Length) { ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (array.Length - index < Count) { ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); } KeyValuePair <TKey, TValue>[] pairs = array as KeyValuePair <TKey, TValue>[]; if (pairs != null) { CopyTo(pairs, index); } else if (array is DictionaryEntry[]) { DictionaryEntry[] dictEntryArray = array as DictionaryEntry[]; Entry[] entries = this.entries; for (int i = 0; i < count; i++) { if (entries[i].hashCode >= 0) { dictEntryArray[index++] = new DictionaryEntry(entries[i].key, entries[i].value); } } } else { object[] objects = array as object[]; if (objects == null) { ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } try { int count = this.count; Entry[] entries = this.entries; for (int i = 0; i < count; i++) { if (entries[i].hashCode >= 0) { objects[index++] = new KeyValuePair <TKey, TValue>(entries[i].key, entries[i].value); } } } catch (ArrayTypeMismatchException) { ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } }
private void Insert(TKey key, TValue value, bool add) { if (key == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } if (buckets == null) { Initialize(0); } if (this.isSimpleKey) { if (this.simpleBuckets.HasOwnProperty(key)) { if (add) { ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); } entries[GetBucket(this.simpleBuckets, key)].value = value; version++; return; } int simpleIndex; if (freeCount > 0) { simpleIndex = freeList; freeList = entries[simpleIndex].next; freeCount--; } else { if (count == entries.Length) { Resize(); } simpleIndex = count; count++; } entries[simpleIndex].hashCode = 1; entries[simpleIndex].next = -1; entries[simpleIndex].key = key; entries[simpleIndex].value = value; SetBucket(simpleBuckets, key, simpleIndex); version++; return; } 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) { ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); } 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++; }