C# Dictionary字典源码分析与自定义Dictionary字典

C# Dictionary字典源码分析与自定义Dictionary字典

官网源码地址:

https://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs

关键点

  • Dictionary实际容器为Entry[] entries 结构体数组
private struct Entry
{
   public int hashCode;
   public int next;
   public TKey key;
   public TValue value;
}
  • entries数组默认长度为3
  • 如果初始化指定长度 entries数组长度为大于指定长度最接近的质数
  • Dictionary查找元素的时间复杂度接近O(1)是因为
    • 定义了一个int[] buckets Hash桶数组
    • 获取key了hashCode
    • 用hashCode除buckets长度取余做为索引(这也是为什么长度为质数的原因)
  • 防止hashCode冲突Dictionary使用了拉链法
    • 使用Entry.next保存冲突项索
  • 当添加值时冲突达到100次会使用新的hashCode方法解决
  • 当Entry[] entries或int[] buckets满了的时候会自动扩了当前容量的2倍
  • 扩容后会重现计算hashcode赋值索引
  • 查找元素是会判断hashcode和key.Equals

优化点

  • 已知容器大小的情况 直接初始化对应大小
  • key最好用简单类型
    • 如果一定要用枚举或引用类型
    • 初始化字典的时候赋值对比函数
    • 或者实现IEquatable
  • 获取值得时候使用TryGetValue不需要先判断ContainsKey

自定义Dictionary字典

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;

public interface IMyDictionary<TKey, TValue> : IEnumerable, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
    TValue this[TKey key] { get; set; }

    ICollection<TKey> Keys { get; }
    ICollection<TValue> Values { get; }

    void Add(TKey key, TValue value);
    bool ContainsKey(TKey key);
    bool Remove(TKey key);
    bool TryGetValue(TKey key, out TValue value);
}


public class MyDictionary<TKey, TValue>
{
    private struct Entry
    {
        public int hashCode;
        public int next;
        public TKey key;
        public TValue value;
    }
    /// <summary>
    /// Hash桶
    /// </summary>
    private int[] buckets;
    /// <summary>
    /// 所有键值对条目数组
    /// </summary>
    private Entry[] entries;
    /// <summary>
    /// 当前entries的index位置
    /// </summary>
    private int count;
    /// <summary>
    /// 当前版本,防止迭代过程中集合被更改
    /// </summary>
    private int version;
    /// <summary>
    /// entries空闲索引
    /// </summary>
    private int freeList;
    /// <summary>
    /// entries空闲数量
    /// </summary>
    private int freeCount;
    /// <summary>
    /// 对比函数
    /// </summary>
    private IEqualityComparer<TKey> comparer;
    /// <summary>
    /// key集合
    /// </summary>
    private KeyCollection keys;
    /// <summary>
    /// value集合
    /// </summary>
    private ValueCollection values;

    public MyDictionary() : this(0, null) { }

    public MyDictionary(IEqualityComparer<TKey> comparer) : this(0, comparer) { }

    public MyDictionary(IDictionary<TKey, TValue> dictionary) : this(dictionary, null) { }

    public MyDictionary(int capacity) : this(capacity, null) { }

    public MyDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : this(dictionary != null ? dictionary.Count : 0, comparer)
    {
        if (dictionary == null) { return; }//异常

        foreach (KeyValuePair<TKey, TValue> pair in dictionary)
        {
            Add(pair.Key, pair.Value);
        }
    }

    public MyDictionary(int capacity, IEqualityComparer<TKey> comparer)
    {
        if (capacity < 0) { throw new Exception("capacity 异常"); }
        if (capacity > 0) Initialize(capacity);
        this.comparer = comparer ?? EqualityComparer<TKey>.Default;
    }

    public TValue this[TKey key]
    {
        get
        {
            int i = FindEntry(key);
            if (i >= 0) return entries[i].value;

            throw new Exception("TKey 异常");
        }
        set
        {
            Insert(key, value, false);
        }
    }

    public IEqualityComparer<TKey> Comparer
    {
        get { return comparer; }
    }

    public KeyCollection Keys
    {
        get
        {
            if (keys == null) keys = new KeyCollection(this);
            return keys;
        }
    }
    public ValueCollection Values
    {
        get
        {
            if (values == null) values = new ValueCollection(this);
            return values;
        }
    }
    public int Count
    {
        get { return count - freeCount; }
    }

    public void Add(TKey key, TValue value)
    {
        Insert(key, value, true);
    }
    public void Clear()
    {
        if (count > 0)
        {
            for (int i = 0; i < buckets.Length; i++) buckets[i] = -1;
            Array.Clear(entries, 0, count);
            freeList = -1;
            count = 0;
            freeCount = 0;
            version++;
        }
    }
    public bool ContainsKey(TKey key)
    {
        return FindEntry(key) >= 0;
    }
    public bool ContainsValue(TValue value)
    {
        if (value == null)
        {
            for (int i = 0; i < count; i++)
            {
                if (entries[i].hashCode >= 0 && entries[i].value == null) return true;
            }
        }
        else
        {
            EqualityComparer<TValue> c = EqualityComparer<TValue>.Default;
            for (int i = 0; i < count; i++)
            {
                if (entries[i].hashCode >= 0 && c.Equals(entries[i].value, value)) return true;
            }
        }
        return false;
    }
    public Enumerator GetEnumerator()
    {
        return new Enumerator(this, Enumerator.KeyValuePair);
    }
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
    }
    public virtual void OnDeserialization(object sender)
    {

    }
    public bool Remove(TKey key)
    {
        if (key == null)
        {
            throw new Exception("异常");
        }

        if (buckets != null)
        {
            int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
            int bucket = hashCode % buckets.Length;
            int last = -1;
            for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next)
            {
                if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))
                {
                    if (last < 0)
                    {
                        buckets[bucket] = entries[i].next;//找到元素后,如果last< 0,代表当前是bucket中最后一个元素,那么直接让bucket内下标赋值为 entries[i].next即可
                    }
                    else
                    {
                        entries[last].next = entries[i].next;//last不小于0,代表当前元素处于bucket单链表中间位置,需要将该元素的头结点和尾节点相连起来,防止链表中断
                    }
                    entries[i].hashCode = -1;
                    entries[i].next = freeList;
                    entries[i].key = default(TKey);
                    entries[i].value = default(TValue);
                    freeList = i;//freeList等于当前的entry位置,下一次Add元素会优先Add到该位置
                    freeCount++;
                    version++;
                    return true;
                }
            }
        }
        return false;
    }
    public bool TryGetValue(TKey key, out TValue value)
    {
        int i = FindEntry(key);
        if (i >= 0)
        {
            value = entries[i].value;
            return true;
        }
        value = default(TValue);
        return false;
    }


    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="capacity">容量</param>
    private void Initialize(int capacity)
    {
        int size = HashHelpers.GetPrime(capacity);//获取该容量匹配的质数
        buckets = new int[size];//初始化桶数组
        for (int i = 0; i < buckets.Length; i++) buckets[i] = -1;//桶数组全部赋值为-1
        entries = new Entry[size];//初始化容量
        freeList = -1;
    }

    /// <summary>
    /// 插入
    /// </summary>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <param name="add"></param>
    private void Insert(TKey key, TValue value, bool add)
    {

        if (key == null)
        {
            throw new Exception("key == null 异常");
        }

        if (buckets == null) Initialize(0);
        int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;//01111111 11111111 11111111 11111111 忽略符号位
        int targetBucket = hashCode % buckets.Length;//获得hashCode在buckets中存放在位置


        int collisionCount = 0;//冲突数量

        //从hash桶中获取索引     i = entries[i].next 继续获取拉链下一个数据
        for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next)
        {
            if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))//如果键值对条目数组索引位置hashCode等于key的hashCode 且key相等 赋值
            {
                if (add)
                {
                    throw new Exception("key已存在 异常");
                }
                entries[i].value = value;
                version++;
                return;
            }
            //如果不相等 冲突+1
            collisionCount++;
        }

        //如果entries[i].next=-1 下一个拉链数据为空则执行下面的操作
        //创建一个拉链数据

        int index;
        if (freeCount > 0)//有空闲位置
        {
            index = freeList;
            freeList = entries[index].next;
            freeCount--;
        }
        else
        {
            if (count == entries.Length)//如果键值对条目数组已满
            {
                Resize();//调整大小
                targetBucket = hashCode % buckets.Length;//重现获取hashCode在buckets中存放在位置
            }
            index = count;//取键值对条目数组空闲的位置
            count++;
        }

        entries[index].hashCode = hashCode;
        entries[index].next = buckets[targetBucket];//把原hash桶中索引的键值对条目索引赋值到当前键值对条目的下一个位
        entries[index].key = key;
        entries[index].value = value;
        buckets[targetBucket] = index;//替换hash桶位的指向
        version++;

        // 如果碰撞次数大于设置的最大碰撞次数,那么触发Hash碰撞扩容
        if (collisionCount > 100 && (comparer == null || comparer == EqualityComparer<TKey>.Default))
        {
            comparer = EqualityComparer<TKey>.Default;//使用新的对比hash函数
            Resize(entries.Length, true);
        }


    }

    /// <summary>
    /// 查找键值对条目
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    private int FindEntry(TKey key)
    {
        if (key == null)
        {
            throw new Exception("key 异常");
        }

        if (buckets != null)
        {
            int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
            for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next)
            {
                //判断hashCode相等且key相等 则返回索引   如果不想等 获取next
                if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
            }
        }
        return -1;
    }

    /// <summary>
    /// 调整大小
    /// </summary>
    private void Resize()
    {
        Resize(HashHelpers.ExpandPrime(count), false);
    }

    /// <summary>
    /// 调整大小
    /// </summary>
    /// <param name="newSize">新da'xia</param>
    /// <param name="forceNewHashCodes">强制使用新的hashcode方法</param>
    private void Resize(int newSize, bool forceNewHashCodes)
    {
        if (newSize >= entries.Length == false) throw new Exception("newSize 异常");

        int[] newBuckets = new int[newSize];//新的hash桶
        for (int i = 0; i < newBuckets.Length; i++) newBuckets[i] = -1;

        Entry[] newEntries = new Entry[newSize];//新的键值对条目数组

        Array.Copy(entries, 0, newEntries, 0, count);//拷贝老的键值对条目数组到新的键值对条目数组

        if (forceNewHashCodes)//强制使用新的hashcode
        {
            for (int i = 0; i < count; i++)
            {
                if (newEntries[i].hashCode != -1)//过滤未使用的
                {
                    newEntries[i].hashCode = (comparer.GetHashCode(newEntries[i].key) & 0x7FFFFFFF);//使用新HashCode函数重新计算Hash值
                }
            }
        }
        for (int i = 0; i < count; i++)
        {
            int bucket = newEntries[i].hashCode % newSize;//获取hash桶索引
            newEntries[i].next = newBuckets[bucket];//第一次 newBuckets[bucket]==-1 第n次 newBuckets[bucket]==上次赋值索引
            newBuckets[bucket] = i;//赋值到hash桶
        }
        buckets = newBuckets;
        entries = newEntries;
    }

    private void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
    {
        if (array == null)
        {
            throw new Exception("异常");
        }

        if (index < 0 || index > array.Length)
        {
            throw new Exception("异常");
        }

        if (array.Length - index < Count)
        {
            throw new Exception("异常");
        }

        int count = this.count;
        Entry[] entries = this.entries;
        for (int i = 0; i < count; i++)
        {
            if (entries[i].hashCode >= 0)
            {
                array[index++] = new KeyValuePair<TKey, TValue>(entries[i].key, entries[i].value);
            }
        }
    }

    public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>,
            IDictionaryEnumerator
    {
        private MyDictionary<TKey, TValue> dictionary;
        private int version;
        private int index;
        private KeyValuePair<TKey, TValue> current;
        private int getEnumeratorRetType;  // What should Enumerator.Current return?

        internal const int DictEntry = 1;
        internal const int KeyValuePair = 2;

        internal Enumerator(MyDictionary<TKey, TValue> dictionary, int getEnumeratorRetType)
        {
            this.dictionary = dictionary;
            version = dictionary.version;
            index = 0;
            this.getEnumeratorRetType = getEnumeratorRetType;
            current = new KeyValuePair<TKey, TValue>();
        }

        public bool MoveNext()
        {
            if (version != dictionary.version)
            {
                throw new Exception("异常");
            }

            // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
            // dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
            while ((uint)index < (uint)dictionary.count)
            {
                if (dictionary.entries[index].hashCode >= 0)
                {
                    current = new KeyValuePair<TKey, TValue>(dictionary.entries[index].key, dictionary.entries[index].value);
                    index++;
                    return true;
                }
                index++;
            }

            index = dictionary.count + 1;
            current = new KeyValuePair<TKey, TValue>();
            return false;
        }

        public KeyValuePair<TKey, TValue> Current
        {
            get { return current; }
        }

        public void Dispose()
        {
        }

        object IEnumerator.Current
        {
            get
            {
                if (index == 0 || (index == dictionary.count + 1))
                {
                    throw new Exception("异常");
                }

                if (getEnumeratorRetType == DictEntry)
                {
                    return new System.Collections.DictionaryEntry(current.Key, current.Value);
                }
                else
                {
                    return new KeyValuePair<TKey, TValue>(current.Key, current.Value);
                }
            }
        }

        void IEnumerator.Reset()
        {
            if (version != dictionary.version)
            {
                throw new Exception("异常");
            }

            index = 0;
            current = new KeyValuePair<TKey, TValue>();
        }

        DictionaryEntry IDictionaryEnumerator.Entry
        {
            get
            {
                if (index == 0 || (index == dictionary.count + 1))
                {
                    throw new Exception("异常");
                }

                return new DictionaryEntry(current.Key, current.Value);
            }
        }

        object IDictionaryEnumerator.Key
        {
            get
            {
                if (index == 0 || (index == dictionary.count + 1))
                {
                    throw new Exception("异常");
                }

                return current.Key;
            }
        }

        object IDictionaryEnumerator.Value
        {
            get
            {
                if (index == 0 || (index == dictionary.count + 1))
                {
                    throw new Exception("异常");
                }

                return current.Value;
            }
        }
    }

    public sealed class KeyCollection : ICollection<TKey>, ICollection
    {
        private MyDictionary<TKey, TValue> dictionary;

        public KeyCollection(MyDictionary<TKey, TValue> dictionary)
        {
            if (dictionary == null)
            {
                throw new Exception("dictionary == null 异常");
            }
            this.dictionary = dictionary;
        }

        public Enumerator GetEnumerator()
        {
            return new Enumerator(dictionary);
        }

        public void CopyTo(TKey[] array, int index)
        {
            if (array == null)
            {
                throw new Exception("array == null 异常");
            }

            if (index < 0 || index > array.Length)
            {
                throw new Exception("index < 0 || index > array.Length 异常");
            }

            if (array.Length - index < dictionary.Count)
            {
                throw new Exception("异常");
            }

            int count = dictionary.count;
            Entry[] entries = dictionary.entries;
            for (int i = 0; i < count; i++)
            {
                if (entries[i].hashCode >= 0) array[index++] = entries[i].key;
            }
        }

        public int Count
        {
            get { return dictionary.Count; }
        }

        bool ICollection<TKey>.IsReadOnly
        {
            get { return true; }
        }

        void ICollection<TKey>.Add(TKey item)
        {
            throw new Exception("异常");
        }

        void ICollection<TKey>.Clear()
        {
            throw new Exception("异常");
        }

        bool ICollection<TKey>.Contains(TKey item)
        {
            return dictionary.ContainsKey(item);
        }

        bool ICollection<TKey>.Remove(TKey item)
        {
            throw new Exception("异常");
        }

        IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()
        {
            return new Enumerator(dictionary);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator(dictionary);
        }

        void ICollection.CopyTo(Array array, int index)
        {
            if (array == null)
            {
                throw new Exception("异常");
            }

            if (array.Rank != 1)
            {
                throw new Exception("异常");
            }

            if (array.GetLowerBound(0) != 0)
            {
                throw new Exception("异常");
            }

            if (index < 0 || index > array.Length)
            {
                throw new Exception("异常");
            }

            if (array.Length - index < dictionary.Count)
            {
                throw new Exception("异常");
            }

            TKey[] keys = array as TKey[];
            if (keys != null)
            {
                CopyTo(keys, index);
            }
            else
            {
                object[] objects = array as object[];
                if (objects == null)
                {
                    throw new Exception("异常");
                }

                int count = dictionary.count;
                Entry[] entries = dictionary.entries;
                try
                {
                    for (int i = 0; i < count; i++)
                    {
                        if (entries[i].hashCode >= 0) objects[index++] = entries[i].key;
                    }
                }
                catch (ArrayTypeMismatchException)
                {
                    throw new Exception("异常");
                }
            }
        }

        bool ICollection.IsSynchronized
        {
            get { return false; }
        }

        Object ICollection.SyncRoot
        {
            get { return ((ICollection)dictionary).SyncRoot; }
        }

        [Serializable]
        public struct Enumerator : IEnumerator<TKey>, System.Collections.IEnumerator
        {
            private MyDictionary<TKey, TValue> dictionary;
            private int index;
            private int version;
            private TKey currentKey;

            internal Enumerator(MyDictionary<TKey, TValue> dictionary)
            {
                this.dictionary = dictionary;
                version = dictionary.version;
                index = 0;
                currentKey = default(TKey);
            }

            public void Dispose()
            {
            }

            public bool MoveNext()
            {
                if (version != dictionary.version)
                {
                    throw new Exception("异常");
                }

                while ((uint)index < (uint)dictionary.count)
                {
                    if (dictionary.entries[index].hashCode >= 0)
                    {
                        currentKey = dictionary.entries[index].key;
                        index++;
                        return true;
                    }
                    index++;
                }

                index = dictionary.count + 1;
                currentKey = default(TKey);
                return false;
            }

            public TKey Current
            {
                get
                {
                    return currentKey;
                }
            }

            Object System.Collections.IEnumerator.Current
            {
                get
                {
                    if (index == 0 || (index == dictionary.count + 1))
                    {
                        throw new Exception("异常");
                    }

                    return currentKey;
                }
            }

            void System.Collections.IEnumerator.Reset()
            {
                if (version != dictionary.version)
                {
                    throw new Exception("异常");
                }

                index = 0;
                currentKey = default(TKey);
            }
        }
    }

    public sealed class ValueCollection : ICollection<TValue>, ICollection
    {
        private MyDictionary<TKey, TValue> dictionary;

        public ValueCollection(MyDictionary<TKey, TValue> dictionary)
        {
            if (dictionary == null)
            {
                throw new Exception("异常");
            }
            this.dictionary = dictionary;
        }

        public Enumerator GetEnumerator()
        {
            return new Enumerator(dictionary);
        }

        public void CopyTo(TValue[] array, int index)
        {
            if (array == null)
            {
                throw new Exception("异常");
            }

            if (index < 0 || index > array.Length)
            {
                throw new Exception("异常");
            }

            if (array.Length - index < dictionary.Count)
            {
                throw new Exception("异常");
            }

            int count = dictionary.count;
            Entry[] entries = dictionary.entries;
            for (int i = 0; i < count; i++)
            {
                if (entries[i].hashCode >= 0) array[index++] = entries[i].value;
            }
        }

        public int Count
        {
            get { return dictionary.Count; }
        }

        bool ICollection<TValue>.IsReadOnly
        {
            get { return true; }
        }

        void ICollection<TValue>.Add(TValue item)
        {
            throw new Exception("异常");
        }

        bool ICollection<TValue>.Remove(TValue item)
        {
            throw new Exception("异常");
        }

        void ICollection<TValue>.Clear()
        {
            throw new Exception("异常");
        }

        bool ICollection<TValue>.Contains(TValue item)
        {
            return dictionary.ContainsValue(item);
        }

        IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
        {
            return new Enumerator(dictionary);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator(dictionary);
        }

        void ICollection.CopyTo(Array array, int index)
        {
            if (array == null)
            {
                throw new Exception("异常");
            }

            if (array.Rank != 1)
            {
                throw new Exception("异常");
            }

            if (array.GetLowerBound(0) != 0)
            {
                throw new Exception("异常");
            }

            if (index < 0 || index > array.Length)
            {
                throw new Exception("异常");
            }

            if (array.Length - index < dictionary.Count)
                throw new Exception("异常");

            TValue[] values = array as TValue[];
            if (values != null)
            {
                CopyTo(values, index);
            }
            else
            {
                object[] objects = array as object[];
                if (objects == null)
                {
                    throw new Exception("异常");
                }

                int count = dictionary.count;
                Entry[] entries = dictionary.entries;
                try
                {
                    for (int i = 0; i < count; i++)
                    {
                        if (entries[i].hashCode >= 0) objects[index++] = entries[i].value;
                    }
                }
                catch (ArrayTypeMismatchException)
                {
                    throw new Exception("异常");
                    throw new Exception("异常");
                }
            }
        }

        bool ICollection.IsSynchronized
        {
            get { return false; }
        }

        Object ICollection.SyncRoot
        {
            get { return ((ICollection)dictionary).SyncRoot; }
        }

        [Serializable]
        public struct Enumerator : IEnumerator<TValue>, System.Collections.IEnumerator
        {
            private MyDictionary<TKey, TValue> dictionary;
            private int index;
            private int version;
            private TValue currentValue;

            internal Enumerator(MyDictionary<TKey, TValue> dictionary)
            {
                this.dictionary = dictionary;
                version = dictionary.version;
                index = 0;
                currentValue = default(TValue);
            }

            public void Dispose()
            {
            }

            public bool MoveNext()
            {
                if (version != dictionary.version)
                {
                    throw new Exception("异常");
                }

                while ((uint)index < (uint)dictionary.count)
                {
                    if (dictionary.entries[index].hashCode >= 0)
                    {
                        currentValue = dictionary.entries[index].value;
                        index++;
                        return true;
                    }
                    index++;
                }
                index = dictionary.count + 1;
                currentValue = default(TValue);
                return false;
            }

            public TValue Current
            {
                get
                {
                    return currentValue;
                }
            }

            Object System.Collections.IEnumerator.Current
            {
                get
                {
                    if (index == 0 || (index == dictionary.count + 1))
                    {
                        throw new Exception("异常");
                    }

                    return currentValue;
                }
            }

            void System.Collections.IEnumerator.Reset()
            {
                if (version != dictionary.version)
                {
                    throw new Exception("异常");
                }
                index = 0;
                currentValue = default(TValue);
            }
        }
    }
}
using System;

public class HashHelpers
{
    public static readonly int[] primes = {
            3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
            1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
            17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
            187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
            1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};

    /// <summary>
    /// 获取质数
    /// </summary>
    /// <param name="min">最小值</param>
    /// <returns></returns>
    public static int GetPrime(int min)
    {
        if (min < 0) { return -1; }//异常


        for (int i = 0; i < primes.Length; i++)
        {
            int prime = primes[i];
            if (prime >= min) return prime;
        }

        //outside of our predefined table. 
        //compute the hard way. 
        for (int i = (min | 1); i < Int32.MaxValue; i += 2)
        {
            if (IsPrime(i) && ((i - 1) % 101 != 0))
                return i;
        }
        return min;
    }

    /// <summary>
    /// 判断是否为质数(素数)
    /// </summary>
    /// <param name="candidate"></param>
    /// <returns></returns>
    public static bool IsPrime(int candidate)
    {
        //与0000 0001位运算  可以把奇数偶数 刷选出来,因为偶数不是质数(2除外)
        if ((candidate & 1) != 0)
        {
            int limit = (int)Math.Sqrt(candidate);//求根号 相当于乘法中的中位数
            for (int divisor = 3; divisor <= limit; divisor += 2)//每次+2是跳过 偶数
            {
                if ((candidate % divisor) == 0)
                    return false;
            }
            return true;
        }
        return (candidate == 2);//最后这个保证2也是质数
    }

    public static int ExpandPrime(int oldSize)
    {
        int newSize = 2 * oldSize;

        // Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
        // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
        if ((uint)newSize > 0x7FEFFFFD && 0x7FEFFFFD > oldSize)
        {
            throw new Exception("oldSize 异常");
        }

        return GetPrime(newSize);
    }
}
posted @ 2020-06-11 16:24  邹强  阅读(1218)  评论(0编辑  收藏  举报