예제 #1
0
        /// <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);
        }
예제 #2
0
        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
        }
예제 #4
0
        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
        }