2010-06-13 88 views
8

除了允许使用散列表之外,还有其他什么原因可以为我的类型实现散列码功能吗?什么时候应该为我的类型定义一个哈希码函数?

假设我正在设计一些我打算在内部使用的类型。我知道类型是系统的“内部”,我也知道我绝不会在散列表中使用这些类型。尽管如此,我决定我将不得不重新定义equals()方法。理论上说我也应该重新定义哈希码的方法,但我看不出任何理由,在这种情况下,我应该这样做。

任何人都可以指出我的其他原因吗?

这个问题可以改为:在哪些情况下我们应该在我们的类型中实现一个哈希码方法。

PS:我不是问如何实现一个。我在询问

回答

10

可能不会 - 但你的任何代码,例如,将使用LINQ?有许多意想不到的地方可能会在你的数据上使用散列表或字典。

如果您不想意外......“有趣”,那么如果您更改Equals,请覆盖GetHashCode。同样,任何IEquatable<T>.Equals都应该与object.Equals实现相匹配。

+0

+1意外的“乐趣”。尼斯转身,马克! – spender 2010-06-13 22:05:48

4

在这种情况下我们应该在我们的类型中实现一个哈希码方法。

简答:只要您覆盖.Equals。因为框架设计指南是这样说的。

6

是的,绝对。 hashCode和equals在同一事物上有两个视图,并且必须一致。集合中的许多例程使用散列码,如果它告诉不同于等于的东西,就会开始行为不端。您可以将“行为不端”理解为“难以置信地发现导致早期头发流失的错误”。

如果您覆盖等于,您必须忽略散列码,而不是因为指导说明如此,而是因为您重视您的头发(或时间)。

现代IDE为您和来自Java Commons或Spring的EqualsBuilder/HashCodeBuilder生成良好的equals/hashcode可以使它更容易。龙目岛项目即时生成它们。

这是一件严重的事情,用这些方法可以做的最好的事情是正确的,并且有成百上千种做错的方式,导致痛苦和痛苦。如果您可以避免自己编写它们,那么请使用生成器或库来帮助您。

+0

Resharper早餐吃平等执行。点,clickety点击,去。 – spender 2010-06-13 22:07:47

+1

IntelliJ:Alt-Ins(Ctrl-N)+用光标+ Enter选择“生成等于/哈希码”。 Eclipse和Netbeans相似。 他们有一个缺点:如果你使用代码度量,这些例程由于圈复杂性而不能遵循所有代码中的所有轨迹,因此这些例程突出显示为痛苦的拇指。所以他们创造了一个可以隐藏其他恶劣程序的环境。 EqualsBuilder/HashcodeBuilder没有这个问题。 – 2010-06-13 22:18:32

+0

*“......但是因为你重视你的头发(或时间)”*。或者生活,如果一个同事必须解决你的混乱。 :-) – 2010-06-13 23:53:38

0

如果你确定你的对象不会在散列表中使用,并且没有使用散列码,那么你可以重写hashCode来抛出一个“未实现”的异常。这比不重写更安全,因为它明确禁止使用该方法,并避免了否则会导致的显着错误。它还会清楚地告诉你该方法是否已被使用。

但是,我个人认为只是使用IDE来生成一个与Equals一致并且可以完成的合理实现。它通常是覆盖equals的值类型,在测试这些时,通常会使用maps,所以实现equals/hashcode API所需的完整合约是有意义的。

相关问题