从内部剖析C# 集合之---- HashTable
这是我在博客园的第一篇文章,写的不好或有错误的地方,望各位大牛指出,不甚感激。
计划写几篇文章专门介绍HashTable,Dictionary,HashSet,SortedList,List 等集合对象,从内部剖析原理,以便在实际应用中有针对性的选择使用。 这篇文章先介绍HashTable 。
先例举几个问题:1,Hashtable为什么速度查询速度快,而添加速度相对慢,且其添加和查询速度之比相差一个数量等级?
2,装填因子( Load Factor)是什么,hashtable默认的装填因子是多少?
3,hashtable里的元素是顺序排序的吗?
4,hashtable内部的数据桶(数组)默认长度多少,其长度为什么只能是素数?
Hashtable中的数据实际存储在内部的一个数据桶里(bucket结构数组),其和普通的数组一样,容量固定,根据数组索引获取值。
下面从正常使用Hashtable场景看内部是如何实现的,内部都做了哪些工作。
一,new一个Hashtable,Hashtable ht=new Hashtable();
Hashtable有多个构造函数,常用的是无参构造函数:Hashtable ht=new Hashtable(),在new一个hashtable时,其内部做了如下工作:调用Hashtable(int capacity,float loadFactor),其中capacity为:0,loadFactor为:1,然后初始化bocket数组大小为3,装载因子为0.72(该值是微软权衡后给的值),如下图所示,该图截取Reflector

二,向Hashtable添加一个元素,ht.Add("a","123")
1,判断当前Hashtable :ht的元素个数与bucket数组之比是否超过装载因子0.72,
1)小于0.72:对a进行哈希取值,然后将得到的值与bucket数组长度进行取模计算,将取模的结果插入到bucket数组对应索引,将“123”赋值其value.
因为哈希值可能会重复(不明白的百度一下),从而导致地址冲突,Hashtable 采用的是 "开放定址法" 处理冲突, 具体行为是把 HashOf(k) % Array.Length 改为 (HashOf(k) + d(k)) % Array.Length , 得出另外一个位置来存储关键字 "a" 所对应的数据, d 是一个增量函数. 如果仍然冲突, 则再次进行增量, 依此循环直到找到一个 Array 中的空位为止。
2) 大于0.72:对bucket数组进行扩容,a, 新建一个数组(该数组的大小为两倍于当前容量最小的素数,比如当前数组长度是3,那么新数组长度为7)。
b,将原来数组元素拷贝到新的数组中,因为bocket数组长度变了,所以需要对所有key重新哈希计算(这是影响hashtable性能的重要因素)。
c, 进行上面a步骤。
三,通过key获取Hashtable对应的value,var v=ht["a"];
1) 计算"a"的哈希值。
2)将计算的结果与bocket数组长度进行取模计算,因为哈希值可能会冲突,所以类似定位索引上的key可能与输入的key不相同,这时继续查找下一个位置。。。。。
3)取模计算结果即是存储在bocket数组上"123"的索引。
Hashtable还有很多方法,比如Clear ,Remove ,ContainsKey,ContainsValue等方法,因篇幅有限这里就不一一介绍了。
写到这里来回答一下篇幅开头的几个问题。
1,Hashtable查询速度快是因为内部是基于数组索引定位的,稍微消耗性能的是取KEY的哈希值,添加性能相对查询慢是因为:a,添加元素时可能会地址冲突,需要重新定位地址 。 b,扩容后 数组拷贝,重新哈希计算旧数组所有key。
2, 装填因子是Hashtable“已存元素个数/内部bucket数组长度”,这个比值太大会造成冲突概率增大,太小会造成空间的浪费。默认是0.72,该值是微软经过大量实验得出的一个比较平衡的值,装填因子范围 0.1<loadFactor<1,否则抛出ArgumentOutOfRangeException异常。
3,不是顺序的(各位看了文章应该知道为什么不是顺序的了吧?)
4,默认长度是3,我看的是.net framework 4.5版本反编译的代码,其他版本的.net framework不确定是不是这个值。为什么扩容的数组长度一定要是素数呢?因为素数有一个特点,只能被自己和1整除,如果不是素数那么在进行取模计算的时候可能会出现多个值。如下图:
今天就写到这,有很多不对或不合理的地方希望各位看到了及时指出,本菜鸟知错就改!!!
先介绍Hashtable,下篇介绍dictionary,到时综合分析在项目中选择使用他们的场景。
从内部剖析C# 集合之---- HashTable的更多相关文章
- 从内部剖析C#集合之HashTable
		
计划写几篇文章专门介绍HashTable,Dictionary,HashSet,SortedList,List 等集合对象,从内部剖析原理,以便在实际应用中有针对性的选择使用. 这篇文章先介绍Hash ...
 - 从内部剖析C# 集合之--Dictionary
		
Dictionary和hashtable用法有点相似,他们都是基于键值对的数据集合,但实际上他们内部的实现原理有很大的差异, 先简要概述一下他们主要的区别,稍后在分析Dictionary内部实现的大概 ...
 - C#基础课程之五集合(HashTable,Dictionary)
		
HashTable例子: #region HashTable #region Add Hashtable hashTable = new Hashtable(); Hashtable hashTabl ...
 - Python开发【数据结构】:字典内部剖析
		
字典内部剖析 开篇先提出几个疑问: 所有的类型都可以做字典的键值吗? 字典的存储结构是如何实现的? 散列冲突时如何解决? 最近看了一些关于字典的文章,决定通过自己的理解把他们写下来:本章将详细阐述上面 ...
 - Java集合——HashMap,HashTable,ConcurrentHashMap区别
		
Map:“键值”对映射的抽象接口.该映射不包括重复的键,一个键对应一个值. SortedMap:有序的键值对接口,继承Map接口. NavigableMap:继承SortedMap,具有了针对给定搜索 ...
 - 【java基础】java集合之HashTable,HashSet,HashMap
		
[一]HashSet (1)HashSet内部维护的是一个HashMap,具体原理见java集合之HashMap [二]HashTable (1)HashTable内部维护的是一个Entry的数组.E ...
 - 【C#集合】Hashtable 和 Dictionary的区别
		
Hashtable 和 Dictionary <K, V> 类型 1):单线程程序中推荐使用 Dictionary, 有泛型优势, 且读取速度较快, 容量利用更充分. 2):Diction ...
 - C#集合之Hashtable
		
Hashtable是一个键值对集合,其泛型版本是Dictionary<K, V>,下面说下常用的一些方法; 1.Add(),向Hashtable添加元素,需要注意的是因为它是键值对集合,所 ...
 - Stack集合、queue集合、hashtable集合
		
1.栈:Stack,先进后出,一个一个赋值,一个一个取值,按顺序. .count 取集合内元素的个数 .push() 将元素一个一个推入集合中//stack集合存入 ...
 
随机推荐
- IOS开发之网络开发工具
			
IOS开发之网络开发工具 做移动端开发 常常会涉及到几个模块:1.网络检測 2.网络请求get和post请求 3.文件上传 4.文件下载 5.断点续传 如今将这些一一分享给大家 ,也欢迎 ...
 - POJ 3614 Sunscreen 优先队列 贪心
			
题意 有C个奶牛去晒太阳 (1 <=C <= 2500),每个奶牛各自能够忍受的阳光强度有一个最小值和一个最大值,太大就晒伤了,太小奶牛没感觉. 而刚开始的阳光的强度非常大,奶牛都承受不住 ...
 - android 72  确定取消对话框,单选对话框,多选对话框
			
package com.itheima.dialog; import android.os.Bundle; import android.app.Activity; import android.ap ...
 - myeclipse 编码问题
			
在使用eclipse+MyEclipse开发中,许多文件编码默认是ISO-8859-1,不支持中文(如常用的JSP),这样我们每次建文件都要手动改编码,其实我们可以在设置文件默认编码,今后再创建时就不 ...
 - Oracle11g安装完成后给用户解锁
			
安装时候你可能忘记给普通用户scott解锁,导致安装成功后普通用户无法登录,那该怎么办呢? 先用system用户登录,登录成功之后就可以给其他用户解锁了. 如图: 同理,如果要锁定某一个用户,只需要把 ...
 - 【Oracle】INSERT INTO SELECT语句和SELECT INTO FROM语句的区别
			
>>>>>>>>>>>>>>>>>>>>>>>>> ...
 - asp.net页面刷新等问题
			
windows.open 关闭当前页面刷新父页面实现() { 在子页面中 Page.ClientScript.RegisterStartupScript(this.GetType(), "a ...
 - Jquery Ajax方法传递json到action
			
ajax向后台传入json需要设置option,如下 contentType:'application/json' data:Json.Stringify(jsObj) 后台处理复杂json对象(不知 ...
 - 为什么要设置Java环境变量(详解)
			
关于java环境变量配置讲解: 1. PATH环境变量.作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序.我们需要把 jdk安装目录下 ...
 - jquery mobile入门资料
			
由于项目中用到了,就去看了一下视频,然后进一步的找找资源,最后自己再总结一遍!(就是动手操作一遍,不论你感觉多简单,只有动手之后,你才有可能有收获) 当然如果你喜欢看文档可以到官网仔细研究,不过喜欢快 ...