hashtable详细介绍
来源:互联网 发布:js怎么创建二维数组 编辑:程序博客网 时间:2024/06/06 18:23
Hashtable存储结构如下
Hashtable是非泛型的集合,所以在检索和存储值类型时通常会发生装箱与拆箱的操作。
当把某个元素添加到 Hashtable 时,将根据键的哈希代码将该元素放入存储桶中,由于是散列算法所以会出现一个哈希函数能够为两个不同的键生成相同的哈希代码,该键的后续查找将使用键的哈希代码只在一个特定存储桶中搜索,这将大大减少为查找一个元素所需的键比较的次数。
Hashtable 的加载因子确定元素与Hashtable 可拥有的元素数的最大比率。加载因子越小,平均查找速度越快,但消耗的内存也增加。默认的加载因子 0.72通常提供速度和大小之间的最佳平衡。当创建 Hashtable 时,也可以指定其他加载因子。
元素总量/ Hashtable 可拥有的元素数=加载因子
当向 Hashtable 添加元素时,Hashtable 的实际加载因子将增加。当实际加载因子达到指定的加载因子时,Hashtable 中存储桶的数目自动增加到大于当前 Hashtable 存储桶数两倍的最小素数。
扩容时所有的数据需要重新进行散列计算。虽然Hash具有O(1)的数据检索效率,但它空间开销却通常很大,是以空间换取时间。所以Hashtable适用于读取操作频繁,写入操作很少的操作类型。
///代码一
static void Main(string[] args) { Hashtable hashtb = new Hashtable(); hashtb.Add(1, "aa"); hashtb.Add(2, "bb"); hashtb.Add(3, "cc"); hashtb.Add(4, "dd"); foreach (DictionaryEntry item in hashtb) { Console.WriteLine(item.Value); item.Value = "ee"; } Console.Read(); }编译出错:item为foreach的迭代变量,无法修改其成员。
代码二
item.Value = "ee";改成hashtb[item.Key] = "ee";
运行报错:集合已修改;可能无法执行枚举操作。
原因:.NET Framework 提供枚举数作为循环访问一个集合的简单方法。枚举数只读取集合中的数据,无法用于修改基础集合。
foreach 语句用于循环访问集合,以获取您需要的信息,但不能用于在源集合中添加或移除项,否则可能产生不可预知的副作用。如果需要在源集合中添加或移除项,请使用 for 循环。
代码三
Thread tr1 = new Thread(new ThreadStart(() => { foreach (DictionaryEntry item in hashtb) { Console.WriteLine(item.Value); } })); tr1.Start(); Thread tr2 = new Thread(new ThreadStart(() => { for (int i = 1; i < 4; i++) { hashtb[i] = "ee"; Console.WriteLine(hashtb[i]); } })); tr2.Start();
线程tr1用来读hashtable,线程tr2用来foreach来枚举修改hashtable,
运行时错误:集合已修改;可能无法执行枚举操作。
代码四
//读取Thread tr1 =new Thread(new ThreadStart(() =>
{
for (int i =1; i<=4; i++)
{
Console.WriteLine(hashtb[i]);
}
}));
tr1.Start();
Thread tr2 =new Thread(new ThreadStart(() =>
{
for (int i =1; i<=4; i++)
{
Console.WriteLine(hashtb[i]);
}
}));
tr2.Start();
//修改
Thread tr3 =new Thread(new ThreadStart(() =>
{
for (int i =1; i<=4; i++)
{
hashtb[i] ="ee";
}
}));
tr3.Start();
运行结果:正常
说明:Hashtable 是线程安全的,可由多个读取器线程和一个写入线程使用。多线程使用时,如果只有一个线程执行写入(更新)操作,则它是线程安全的,从而允许进行无锁定的读取(若编写器序列化为 Hashtable)
代码五
Thread tr1 = new Thread(new ThreadStart(() => { lock (hashtb) { foreach (DictionaryEntry item in hashtb) { Console.WriteLine(item.Value); } } })); tr1.Start(); Thread tr2 = new Thread(new ThreadStart(() => { lock (hashtb) { for (int i = 1; i <= 4; i++) { hashtb[i] = "ee"; } } })); tr2.Start();
运行结果:正常
说明:由于两个线程里面都加了lock (hashtb)所以是线程安全的。 从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合,或者捕捉由于其他线程进行的更改而引发的异常。
Hashtable 提供的线程安全方法
Hashtable的Synchronized静态方法提供线程安全的实例,如下:
Hashtable ht = Hashtable.Synchronized(new Hashtable());
内部实现如下:
public override void Add(object key, object value){ lock (this._table.SyncRoot) { this._table.Add(key, value); }}
按输入方式输出
因为hashtable内部是无序的,所以输出不一定,hashtable取数据的机制没搞明白。按照下面代码可以实现先进先出。
可以通过控制ArrayList里面keys的排序来控制hashtable的输出,当然也可以用SortedDictionary和SortedList实现排序集合。
public class NoSortHashtable : Hashtable { private ArrayList keys = new ArrayList(); public NoSortHashtable() { } public override void Add(object key, object value) { base.Add (key, value); keys.Add (key); } public override ICollection Keys { get { return keys; } } public override void Clear() { base.Clear (); keys.Clear (); } public override void Remove(object key) { base.Remove (key); keys.Remove (key); } public override IDictionaryEnumerator GetEnumerator() { return base.GetEnumerator (); } }
- hashtable详细介绍
- HashTable详细介绍(一)
- java Hashtable详细介绍(源码解析)和使用示例
- HashTable介绍
- Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
- Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
- Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
- Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
- Java【集合系列】-11- Hashtable详细介绍(源码解析)和使用示例
- HashTable源码简单介绍
- HashTable的一个详细实现
- C# HashTable 简单操作介绍
- hashMap 和 hashTable 简单介绍
- HashMap和Hashtable的详细区别
- stl源码剖析 详细学习笔记 hashtable
- 史上最详细的Hashtable详解--源码分析
- HashMap和Hashtable的详细区别
- hashmap和hashtable的介绍和区别
- DP + math 之 Codeforces 126D - Fibonacci Sums
- Go如何发送广播包
- ZC301摄像头,OK6410的开发板,linux3.0.1,内核Oops的解决方法
- CloudTV Based on WebRTC(基于WebRTC的云电视)
- 4 Reasons why SharePoint is Dying 四个理由告诉你,为什么SharePoint即将死去
- hashtable详细介绍
- 机房收费系统系列一:运行时错误‘-2147217843(80040e4d)’;用户‘sa’登陆失败
- poj 2411 Mondriaan's Dream
- Android检测是否安装了指定应用
- 1197: [HNOI2006]花仙子的魔法
- 特征值和特征向量
- 最开的收款金额为本命尽快的贺卡
- 今天开始 遨游CSDN 学如逆水行舟!【于 深圳】
- 的撒即可不美观春天又来到啊垫块机咯可