C# Dictionary内部实现与Hashtable的比较

首先解释什么是哈希表。

哈希表是类似<key,value>的一个键值对集合, key和 value都属于object类型。也就反应了它存在的一个问题:类型安全问题。

比如我可以hs.add("name","susu");同样可以添加hs.add("age",28).这样的话,在访问时就存在类型错误的问题。

而Dictionary,属于Hashtable的一种泛型实现,保证了类型安全问题。也就是如果存储的类型是值类型,那就避免了装箱操作。那

Dictionary内部是一个怎样的实现过程呢。

首先这里附上我参考的博文,我这里只说大概,原来还是看人家的。

https://www.youkuaiyun.com/gather_21/MtTagg4sMDM4LWJsb2cO0O0O.html

它由两部分组成,一部分为一个int数组,另一部分为一个哈希表。

private void Initialize(int capacity)
        {
            int prime = HashHelpers.GetPrime(capacity);
            this.buckets = new int[prime];
            for (int i = 0; i < this.buckets.Length; i++)
            {
                this.buckets[i] = -1;
            }
            this.entries = new Entry<TKey, TValue>[prime];
            this.freeList = -1;
        }

 有一个buckets整型数组,用来进行计算Hah碰撞。entries用来存储字典中的内容,并且标示下一个元素的位置。

这里涉及到一个分配字典长度的问题。不是说你在字典中添加一个元素,它的长度就添加1.在其内部,是以素数的方式增加。

类似:3,7,11,13,17.....这种,以达到均匀分配的目的。

比如当你的字典长度从7变成8时,实际上字典内部分配的空间是从7变成11,而不是8.

加入新的keyvalue时,首先进行buckets碰撞,这里使用的方法是除留余数法,如果发现buckets下标==-1,说明它没有被使用,这时将值存储到entries中。如果后进入的元素通过碰撞发现在buckets中已经占用,则会生成一个链表。新的entries指向上一个entries的下标。

当对字典进行删除操作时,同样会进行哈希碰撞,会在freelist里进行存储。后续的加入也是优先查看freelist中是否有剩余长度可用。

 

至于哈希表和字典的区别,有以下几点,只做概括:

[1] 单线程程序中推荐使用 Dictionary, 有泛型优势, 且读取速度较快, 容量利用更充分.
[2] 多线程程序中推荐使用 Hashtable, 默认的 Hashtable 允许单线程写入, 多线程读取, 对 Hashtable 进一步调用 Synchronized() 方法可以获得完全线程安全的类型. 而 Dictionary 非线程安全, 必须人为使用 lock 语句进行保护, 效率大减.
[3] Dictionary 有按插入顺序排列数据的特性 (注: 但当调用 Remove() 删除过节点后顺序被打乱), 因此在需要体现顺序的情境中使用 Dictionary 能获得一定方便.

这里附上另一篇对于字典和哈希表的比较博文。

https://www.cnblogs.com/zk-zhou/p/6672494.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值