从内部剖析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整除,如果不是素数那么在进行取模计算的时候可能会出现多个值。

时间: 2024-08-06 10:24:56

从内部剖析C#集合之HashTable的相关文章

从内部剖析C# 集合之--Dictionary

Dictionary和hashtable用法有点相似,他们都是基于键值对的数据集合,但实际上他们内部的实现原理有很大的差异, 先简要概述一下他们主要的区别,稍后在分析Dictionary内部实现的大概原理. 区别:1,Dictionary支持泛型,而Hashtable不支持. 2,Dictionary没有装填因子(Load Facto)概念,当容量不够时才扩容(扩容跟Hashtable一样,也是两倍于当前容量最小素数),Hashtable是"已装载元素"与"bucket数组长

支付宝系统架构内部剖析

本文转载于网上的文章 <最全最强解析:支付宝系统架构内部剖析(架构图)>. 最早的出处没有找到,原文作者也未知. 如果你知道请告诉我. 支付宝系统架构概况 典型处理默认 资金处理平台 财务会计 支付清算 核算中心 交易 柔性事务 消息系统 数据分布 数据缓存 支付宝技术产品线 支付宝的开源分布式消息中间件–Metamorphosis(MetaQ) 貌似原发起者离开了阿里,现在这个项目改名为RocketMQ Metamorphosis (MetaQ) 是一个高性能.高可用.可扩展的分布式消息中间

转 最全最强解析:支付宝钱包系统架构内部剖析(架构图)

原文: 最全最强解析:支付宝钱包系统架构内部剖析(架构图) 2015/06/05 支付宝系统架构概况 典型处理默认 资金处理平台 财务会计 支付清算 核算中心 交易 柔性事务 支付宝的开源分布式消息中间件–Metamorphosis(MetaQ) Metamorphosis (MetaQ) 是一个高性能.高可用.可扩展的分布式消息中间件,类似于LinkedIn的Kafka,具有消息存储顺序写.吞吐量大和支持本地和XA事务等特性,适用 于大吞吐量.顺序消息.广播和日志数据传输等场景,在淘宝和支付宝

C#集合之Hashtable

Hashtable是一个键值对集合,其泛型版本是Dictionary<K, V>,下面说下常用的一些方法; 1.Add(),向Hashtable添加元素,需要注意的是因为它是键值对集合,所以要同时添加一个键和一个值,且键不能重复. 2.ContainsKey(key)方法,是查询是否包含某个键,其Contains()方法最终也是调用这个方法实现的. 3.ContainsValue(value)方法,是查询是否包含某个值. 4.hash[“key”],根据键获取某个值.hash[“key”]=“

[转] 支付宝系统架构内部剖析

本文转载于网上的文章 <最全最强解析:支付宝系统架构内部剖析(架构图)>. 最早的出处没有找到,原文作者也未知. 如果你知道请告诉我. 支付宝系统架构概况 典型处理默认 资金处理平台 财务会计 支付清算 核算中心 交易 柔性事务 消息系统 数据分布 数据缓存 支付宝技术产品线 支付宝的开源分布式消息中间件–Metamorphosis(MetaQ) 貌似原发起者离开了阿里,现在这个项目改名为RocketMQ Metamorphosis (MetaQ) 是一个高性能.高可用.可扩展的分布式消息中间

C#集合类型——Hashtable、Dictionary之浅谈

Hashtable表 数组.数组集合.List集合都是通过索引来访问里面成员.哈希表则是通过键来访问成员值.键不可为空,值可为空. 比如: Hashtable  hash=new  Hashtable(); hash.Add("one","chen"); hash.Add("two","li"); Console.WriteLine(hash["one"]); 运行结果:chen 基本的常用方法 1,添加

15-07-10 Stack集合、queue集合、hashtable集合

1.栈:Stack,先进后出,一个一个赋值,一个一个取值,按顺序. .count           取集合内元素的个数 .push()         将元素一个一个推入集合中//stack集合存入用.push() .pop()           将元素一个个弹出集合 .clear()         清空集合 Stack s = new Stack();//先存入的后取出 s.Push(1); s.Push(2); s.Push(3); Console.WriteLine(s.Pop())

集合之HashTable

在java中与有两个类都提供了一个多种用途的hashTable机制,他们都可以将可以key和value结合起来构成键值对通过put(key,value)方法保存起来,然后通过get(key)方法获取相对应的value值.一个是前面提到的HashMap,还有一个就是马上要讲解的HashTable.对于HashTable而言,它在很大程度上和HashMap的实现差不多,如果我们对HashMap比较了解的话,对HashTable的认知会提高很大的帮助.他们两者之间只存在几点的不同,这个后面会阐述. 一

双列集合之hashtable

一.hashtable和ArrayList的性能比较 hashtable比ArrayList取值更快.原因是前者是根据键直接取值,但是ArrayList是循环整个集合,找到需要的元素. 二.hashtable的用法 1 static void Main(string[] args) 2 { 3 Hashtable hs = new Hashtable(); 4 hs.Add("zs","张三"); 5 hs.Add("ls", "李四&