【问题标题】:How to avoid collisions using HashCode.Combine?如何使用 HashCode.Combine 避免冲突?
【发布时间】:2019-05-16 00:24:51
【问题描述】:

我在构建具有相当小的数据集(约 100k 行)的哈希表时遇到了冲突。我在这里做错了吗?

这是一个 2 位数据的示例,通常会生成相同的哈希值。 (偶尔运行会产生不同的哈希值):

long long1 = 330765;
long long2 = 227691;
DateTime date1= new DateTime(2016, 5, 24);
DateTime date2= new DateTime(2016, 1, 25);

var c1 = HashCode.Combine(long1, date1);
var c2 = HashCode.Combine(long2, date2);
Console.WriteLine(c1);
Console.WriteLine(c2);

可通过 dotnetcore 2.1 重现

【问题讨论】:

  • 你用什么来组合?你必须小心“DataTable”和“Data”+“Table”都给出相同的哈希值。为了防止重复,您通常会在组合时使用“Data”+“^”+“Table”,这样您就会得到两个不同的哈希值。
  • 100k 个项目的冲突是可预期的行为。
  • 这是标准的生日问题。在 32 位空间中与 100k 个项目发生冲突的概率为 68%。
  • @MikeZboray 具有完美的散列和随机数据。所以这是最好的情况。如果数据不是随机的,或者散列不完善,它可以从那里上升。
  • @Servy 是的,我打算添加它。组合并不完美,输入数据可能没有覆盖完整的键空间,当然简单的哈希表没有那么多桶。

标签: c# hash .net-core


【解决方案1】:

您可以从不完全避免与哈希码发生冲突(除了具有少于 2^32 个可能的不同值的类型,如短裤或字节或类似的东西)。编写一个好的散列仅仅意味着尽可能地减少你的冲突。您可以通过尽力确保您的哈希码(大约)均匀分布在int 的整个范围内来做到这一点。

您还可以尝试避免某些通常一起使用的值发生冲突(例如,您可以提出一种日期生成算法,使同一周内的日期不会发生冲突,并确保所有冲突都发生在相距较远的日期中比那个)。

但是任何时候你使用生成的哈希码,你都需要有一些机制来处理冲突。

【讨论】:

  • 您能否提供一个示例/网址来说明您可以实施以减轻冲突的机制?
  • 澄清一下,我的意思是第三段*。
  • 处理并不意味着减少冲突。这意味着有一些行为来处理它们发生的罕见情况。考虑 Dictionary 类。它使用哈希码来计算存储桶,然后在存储桶中放入一个数组而不是单个元素。这意味着通过枚举该数组来处理冲突,直到找到它(或没有)。
  • @Servy :绝对错误!!!散列应该只是第一级检查项目是否相等。在哈希比较之后,您总是需要比较对象以确保您正在使用哪个副本。使用散列的比较返回 List。因此,如果您查看 msdn IEqualityComparer(请参阅:docs.microsoft.com/en-us/dotnet/api/…)。在调用 GetHashCode() 之后,调用 Equals() 并且在 equal 中,您必须测试键匹配以避免冲突。
  • @jdweng 1) 不,你之前没有这么说 2) 我从来没有说过你应该编写偶尔会出错的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多