很抱歉将两个问题合并为一个,它们是相关的。
对于HashCode
来说, HashSet
等等。据我了解,它们必须是唯一的,而不是更改,并将对象的任何配置表示为单个数字。
我的第一个问题是,对于我的对象,包含两个Int16 a
和b
,我的GetHashCode
可以安全地返回a * n + b
之类的内容,其中n是很多,我想也许Math.Pow(2, 16)
?
同样GetHashCode
似乎不能特别地返回Int32类型。
32位可以存储,例如,两个Int16,一个unicode字符或16个N,S,E,W指南针方向,它不是很多,甚至像一些小节点图可能对它来说太多了。这是否代表了C#Hash集合的限制?
答案 0 :(得分:7)
据我了解,它们必须是唯一的
不。对于大多数类型而言,它们不可能是唯一的,其可能具有超过2个 32 可能的值。理想情况下,如果两个对象具有相同的哈希码,那么它们不太可能相等 - 但您永远不应该假设它们 相等。重要的是,如果他们有不同的哈希码,他们肯定应该不等。
我的第一个问题是,对于我的对象,包含两个Int16s a和b,我的GetHashCode返回类似* n + b的东西是安全的,其中n是一个很大的数字,我想也许Math.Pow(2 ,16)。
如果只包含两个Int16
值,则最简单的方法是使用:
return (a << 16) | (ushort) b;
然后值 将是唯一的。 Hoorah!
同样
GetHashCode
似乎也不明确地返回Int32
类型。
是。 Dictionary
和HashSet
等类型需要能够使用固定大小,以便他们可以使用它将值放入存储区。
32位可以存储,例如,两个Int16,一个unicode字符或16个N,S,E,W指南针方向,它不是很多,甚至像一些小节点图可能对它来说太多了。这是否代表了C#Hash集合的限制?
如果它 是一个限制,它将是一个.NET限制而不是C#限制 - 但不是,它只是对哈希代码所代表的误解。
Eric Lippert有一个很好的(显然)blog post about GetHashCode
,您应该阅读以获取更多信息。
答案 1 :(得分:1)
GetHashCode
不是(也不可能)对象的每个实例都是唯一的。以Int64
为例;即使散列函数是完美分布的,也会有 two 40亿 Int64
散列到每个值,因为哈希码就像你提到的那样,只有Int32
。
然而,这不是对使用哈希码的集合的限制;它们只是对使用哈希值相同的元素使用存储桶。因此,不能保证对哈希表的查找是单个操作。获取正确的存储桶只需一个操作,但该存储桶中可能有多个项目。