c#中哈希表的使用(键的问题)

在c#中,使用Hashtable的关键是键和哈希函数,Hashtable根据键用哈希函数生成value的哈希代码。在查找的时候用key值根据同一个哈希函数生成哈希代码,并且搜索与该哈希代码想关联的value从而取出key对应的value。

 

在C# 的自定义对象中,有默认的GetHashCode方法 。但GetHashCode 方法的默认实现不保证针对不同的对象返回唯一值。而且,.NET Framework 不保证 GetHashCode 方法的默认实现以及它所返回的值在不同版本的 .NET Framework 中是相同的。因此,在进行哈希运算时,该方法的默认实现不得用作唯一对象标识符。

GetHashCode 方法可以由派生类型重写。值类型必须重写此方法,以提供适合该类型的哈希函数和在哈希表中提供有用的分布。为了获得最佳结果,哈希代码必须基于实例字段或 属性(而非静态字段或属性)的值。

用作 Hashtable 对象中键的对象必须重写 GetHashCode 方法,因为这些对象必须生成其各自的哈希代码 。如果用作键的对象不提供 GetHashCode 的有用实现,您可以在构造 Hashtable 对象时指定哈希代码提供程序。从 2.0 版开始,哈希代码提供程序基于 System.Collections. IEqualityComparer 接口。

 

MSDN中队哈希函数对实现者的说明:

哈希函数用于快速生成一个与对象的值相对应的数字(哈希代码)。哈希函数通常是特定于每个 Type 的,而且,必须至少使用一个实例字段作为输入。

哈希函数必须具有以下特点:

  • 如果两个对象的比较结果相等,则每个对象的 GetHashCode 方法都必须返回同一个值。但是,如果两个对象的比较结果不相等,则这两个对象的 GetHashCode 方法不一定返回不同的值。

  • 一个对象的 GetHashCode 方法必须总是返回同一个哈希代码,但前提是没有修改过对象状态,对象状态用来确定对象的 Equals 方法的返回值。请注意,这仅适用于应用程序的当前执行,再次运行该应用程序时可能会返回另一个哈希代码。

  • 为了获得最佳性能,哈希函数必须为所有输入生成随机分布。

在c#中,String是内置类型, String 类提供的 GetHashCode 方法的实现为相同的字符串值返回相同的哈希代码。因此,如果两个 String 对象表示相同的字符串值,则它们返回相同的哈希代码。另外,该方法使用字符串中的所有字符生成相当随机的分布式输出,即使当输入集中在某些范围内时(例 如,许多用户可能有只包含低位 128 个 ASCII 字符的字符串,即使字符串可以包含 65,535 个 Unicode 字符中的任何字符)。

 

对于 Object 的派生类,当且仅当此派生类将值相等性定义为引用相等并且类型不是值类型时,GetHashCode 方法才可以委托给 Object. GetHashCode 实现。

 

在类上提供好的哈希函数可以显著影响将这些对象添加到哈希表的性能。在具有好的哈希函数实现的哈希表中,搜索元素所用的时间是固定的(例如运算复杂度为 O(1) 的运算)。而在具有不好的哈希函数实现的哈希表中,搜索性能取决于哈希表中的项数(例如运算复杂度为 O(n ) 的运算,其中的 n 是哈希表中的项数)。哈希函数的计算成本也必须不高。

GetHashCode 方法的实现必须不会导致循环引用。例如,如果 ClassA.GetHashCode 调用 ClassB.GetHashCodeClassB.GetHashCode 必须不直接或间接调用 ClassA.GetHashCode

GetHashCode 方法的实现必须不引发异常。

重写 GetHashCode 的派生类还必须重写 Equals , 以保证被视为相等的两个对象具有相同的哈希代码;否则,Hashtable 类型可能无法正常工作。

 

根据以上的描述,我得出两个结论:

第一:在C# 中使用Hashtable, 选择String作为键(key)是比较合适的。用String作为key,不用自己去实现GetHashCode方法而能获得比较好的搜索性能,对于使用哈希函数比较困难的情况或者哈希函数难以选择的 情况比较合适。

第二: 如果键(key)必须是自定义类型,则必须选择合适的哈希函数并实现 GetHashCode方法。在此种情况下,自定义中字段的选取与哈希函数的选取一定要科学,散列性能要良好,否则Hashtable的性能会大大下降。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值