Hashtable 允许我们通过键来寻找保存在其中的值,还可以通过 ContainsKey 方法来查看是否在 Hashtable 中有对应的键,但是,在使用中还是有一些需要注意的地方。

一个同学写了这样一段使用 Hashtable 的代码,发现一个奇怪的问题。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Collections;
  6 using System.Threading;
  7 
  8 namespace HashtableDemo
  9 {
 10     class Program
 11     {
 12         static void Main(string[] args)
 13         {
 14             //第一次输出 
 15             // not
 16             Hashtable ha = new Hashtable();
 17             for (int i = 0; i < 5; i++)
 18                 ha.Add(new cuskey(i), i);
 19 
 20             if (ha.ContainsKey(new cuskey(3)))
 21                 Console.WriteLine("find");
 22             else
 23                 Console.WriteLine("Can't find");
 24 
 25             ha.Clear();
 26 
 27             //第二次输出 
 28             // ok
 29             MyTest t = new MyTest(10);
 30             ha.Add(t, 10);
 31             if (ha.ContainsKey(new MyTest(10)))
 32             {
 33                 Console.WriteLine("find");
 34             }
 35             else
 36                 Console.WriteLine("Can't find");
 37 
 38             //第三次输出 
 39             // ok
 40             Console.WriteLine(ha[new MyTest(10)]);
 41 
 42             //第四次输出 
 43             // 
 44             t.KeyNum = 11;
 45 
 46             if (ha.ContainsKey(new MyTest(11)))
 47             {
 48                 Console.WriteLine("find 11");
 49             }
 50             else if (ha.ContainsKey(new MyTest(10)))
 51                 Console.WriteLine("find 10");
 52             else
 53                 Console.WriteLine("Can't find");
 54 
 55 
 56 
 57             //第五次输出 
 58             Console.WriteLine(ha.Count);
 59 
 60             //第六次输出 
 61             MyTest mt = new MyTest(11);
 62             ha.Add(mt, 11);
 63             Console.WriteLine(ha.Count);
 64 
 65             //第七次输出 
 66             foreach (DictionaryEntry item in ha)
 67             {
 68                 Console.WriteLine((item.Key as MyTest).KeyNum);
 69                 Console.WriteLine(item.Value);
 70             }
 71 
 72             Console.ReadLine();
 73         }
 74     }
 75 
 76     class MyTest
 77     {
 78         int keyNum;
 79 
 80         public int KeyNum
 81         {
 82             get { return keyNum; }
 83             set { keyNum = value; }
 84         }
 85 
 86         public MyTest(int num)
 87         {
 88             keyNum = num;
 89         }
 90 
 91         public override int GetHashCode()
 92         {
 93             return keyNum;
 94         }
 95 
 96         public override bool Equals(object obj)
 97         {
 98             return keyNum == ((MyTest)obj).KeyNum;
 99         }
100     }
101 
102     class cuskey
103     {
104         int keyNum;
105 
106         public int KeyNum
107         {
108             get { return keyNum; }
109             set { keyNum = value; }
110         }
111 
112         public cuskey(int num)
113         {
114             keyNum = num;
115         }
116     }
117 }

然后,发现一个问题:

在第四次我用了两个键去匹配,都是Can't find,但是在第七次输出的时候怎么就能找到确实是KeyNum=11的实例,这是怎么回事???

当我们在 Hashtable 中通过键来保存值的时候,Hashtable 会通过键对象的 HashCode 来确定内容保存在表中的位置,同时还要保存这个键对象的引用。

当我们通过 ContainsKey 来查找的时候,Hashtable 将会取得用来查找的键对象的 HashCode ,计算出在 Hashtable 中相应的位置,然后,在这个位置取出保存的键, 与现在的查找对象的 HashCode 去比较。

在第四次的时候,使用 11 的时候,计算出的 Hashcode 将在 11 所对应的位置。但是,原来通过 10 保存,现在使用 HashCode 11 来查找,所以,这个位置中没有保存数据,所以找不到。
在使用 10 的时候,在这个位置上有保存的键,但是,通过 Equals 方法判断两个对象不相同,所以,也找不到。

但是,在 Hashtable 中确实保存着一个条目。所以,在第七次的时候可以遍历到。

所以,如果通过一个对象作为键在 Hashtable 中保存数据,那么,一旦修改了这个键对象,就可能没有办法通过键对象来找到原来保存的值。

在需要修改键对象的时候,正确的方式是,先移除原来的键值对,然后修改键对象,最后,使用修改之后的键对象来保存新的键值对。

在 CLR Via C# 中文 第三版的 130 页中间,Jeffrey 也提到了这个问题。

Hashtable 中的键值修改问题相关推荐

  1. 自制Windows 7 注册表键值修改服务(Service)

    首先说说为什么要写这么一个服务.由于电脑要在公司域中使用,所以不可避免的会继承域中的组策略配置.域中95% 的计算机是XP系统,部分组策略对于Windows 7 系统来说有些多余而且带来很多麻烦. 问 ...

  2. 适用于QMK的键值修改软件VIA

    QMK可以方便的修改每个键位的键值,比如将QWERT改为小众的DVORAK布局,自定义组合键,自定义宏什么的.但每次修改都需要重新编译,刷固件,这就比较麻烦了.借助动态键值修改软件 VIA(https ...

  3. 如何在 bash 中使用键值字典

    在字典中,字典存储一组键,每个键都有一个与之关联的值.可以使用对应的键在字典中插入.检索或更新值.字典数据结构针对基于键值的快速检索进行了优化,因此通常使用哈希表来实现.在不同的编程语言中,字典通常有 ...

  4. @PropertySource读取外部配置文件中的k-v保存到运行的环境变量中,加载完微博的配置文件以后使用${}取配置文件中的键值

    @PropertySource读取外部配置文件中的k-v保存到运行的环境变量中,加载完微博的配置文件以后使用${}取配置文件中的键值 该注解value={},可以使用String数组形式,读取多个配置 ...

  5. Java删除properties配置文件中指定键值的代码

    将开发过程较好的一些内容片段记录起来,下面的内容段是关于Java删除properties配置文件中指定键值的内容. public static boolean deleteKeyValue4Pro(S ...

  6. delphi中combobox键值对

    delphi中combobox键值对 2010-09-13 10:46:51|  分类: 默认分类 |  标签: |字号大中小 订阅 1.添加键值对: cbb1.Items.AddObject('显示 ...

  7. Redis中的键值过期操作

    1.过期设置 Redis 中设置过期时间主要通过以下四种方式: expire key seconds:设置 key 在 n 秒后过期: pexpire key milliseconds:设置 key ...

  8. python中字典的键是唯一的吗_python 零散记录(四) 强调字典中的键值唯一性 字典的一些常用方法...

    dict中键只有在值和类型完全相同的时候才视为一个键: mydict = {1:1,'':1} #此时mydict[1] 与 mydict['1']是两个不同的键值 dict的一些常用方法: clea ...

  9. java redis 过期_Redis中的键值过期操作

    1.过期设置 Redis 中设置过期时间主要通过以下四种方式: expire key seconds:设置 key 在 n 秒后过期: pexpire key milliseconds:设置 key ...

最新文章

  1. 语音合成模块 文本转TTS 真人发音 SYN6288
  2. Fiddler抓包使用教程-模拟低速网络环境
  3. 【转】刨根究底字符编码之十六——Windows记事本的诡异怪事:微软为什么跟联通有仇?
  4. matplotlib的优点_超详细matplotlib基础介绍!!!
  5. LeetCode 动态规划《简单》部分 Python实现
  6. 百度谷歌2013年母亲节 赏析中文搜索引擎庆祝涂鸦
  7. Atitit.ide代码块折叠插件 eclipse
  8. jQuery下载及基本使用
  9. MNE溯源fieldtrip官网教程
  10. 爬虫抓取究竟是什么?
  11. 基于Node.js的3DTiles三维倾斜摄影模型爬虫
  12. 函数:判断一个整数是否既是5又是7的整倍数
  13. 两个取得卓越业绩的关键因素
  14. CCF-CSP—2017.12.—4 行车路线(spfa) 题解
  15. Python全套视频
  16. Excel数据可视化图表设计需要注意的几个问题
  17. vc中定时器并非多线程
  18. Mysql数据库--自学笔记--2
  19. 计算机中逻辑移位示意图,定点数运算之移位运算(收藏)
  20. 聊聊关于复杂调查加权中权重对数据的分布影响

热门文章

  1. es分布式结构原理是什么?
  2. css规则中区块block,css常用属性总结:背景background下篇
  3. Spring boot 实战 利用 Sharding-jdbc实现数据库的读写分离
  4. devDependencies和dependencies的区别
  5. endnote转化成纯文本后_如何用Endnote分分钟搞定参考文献
  6. c语言中输入位权1,精通C语言程序设计1-编程基础.pptx
  7. java 内存测试_请你说一下java jvm的内存机制
  8. pytorch统计矩阵非0的个数_PyTorch常见的12坑
  9. DWZ(J-UI)selectedToDo操作完成后刷新Tab
  10. 自定义notebook扩展插件_Jupyter notebook安装扩展插件