简体   繁体   English

相等的对象=相等的Hashcode结果,java

[英]Equal object = Equal Hashcode consequences, java

What are the "worst case" consequences (real world scenarios here), if I have an object (ie a bean) which has a solid, meaningful equals() method, but lacks a complementary hashCode() method? 如果我有一个对象(即Bean)具有可靠的,有意义的equals()方法,但缺少互补的hashCode()方法,那么“最坏情况”的后果是什么(这里是现实情况hashCode() It seems like most APIs use the equals() and compareTo() methods for maintaining collections. 似乎大多数API使用equals()compareTo()方法来维护集合。 I'm wondering when is the hashCode() most important? 我想知道hashCode()最重要?

The worst-case consequences are that the hash table won't work . 最坏的情况是哈希表不起作用 For example, lets assume that you've got a simple class like this: 例如,假设您有一个像这样的简单类:

public class StringWrapper {
    private String value;
    ...
    public boolean equals(Object other) {
        // two objects are equal if their respective values are equal ... using `equals`.
    }
    // No hashcode override.
}

Here we have a class we have a class does not obey one of the required invariants of the equals/hashcode contract. 在这里,我们有一个类,我们有一个类不服从equals / hashcode合约的必需不变式之一。 Specifically, two instances cal be equal, but have different hashcodes. 具体来说,两个实例可以相等,但是具有不同的哈希码。

When you add two different instances of this class to a HashSet, you may end up with both instances in the set ... on different hash chains. 将此类的两个不同实例添加到HashSet时,最终可能会在set中两个实例都位于不同的哈希链上。 You get similar anomalies when removing objects from the set, testing to see if the set contains an object, and so on. 从集合中删除对象,进行测试以查看集合中是否包含对象时,您会遇到类似的异常情况。

(Note that you may get lucky, and have the two instances end up on the same hash chain despite having different hashcodes. But your luck could change when some other unrelated object is added to the hash table, causing it to automatically resize. The resize is liable to cause entries with different hashcodes to be redistributed to different hash chains.) (请注意,您可能会很幸运,尽管哈希码不同,但两个实例仍位于同一哈希链上。但是,如果将其他一些不相关的对象添加到哈希表中,您的运气可能会发生变化,从而导致其自动调整大小。可能导致具有不同哈希码的条目重新分配给不同的哈希链。)


So I'm wondering... when is the hashcode most important ? 所以我想知道...哈希码什么时候最重要?

It is always important. 这始终很重要。

Or to put it another way, it is only unimportant when you know with 100% certainty that instances of the class are never ever going to be used in hash tables. 或者换句话说,只有当您以100%的确定性知道永远不会在哈希表中使用该类的实例时,这才是不重要的。 (And I don't know how you can know that, unless you delete all copies of the class. And that renders the whole question moot!) (而且我不知道您怎么知道,除非您删除该类的所有副本。这使整个问题变得毫无意义!)


UPDATE UPDATE

@supercat mentioned the case where you can't write a decent hashcode. @supercat提到了无法编写体面的哈希码的情况。

If there is some good reason you can't write a half-decent hashcode() method, I'd advocate overriding it to throw UnsupportedOperationException or some such. 如果有一些很好的理由,您不能编写一个像样的hashcode()方法,我建议您重写它以抛出UnsupportedOperationException或类似的方法。 That way you get a fast-fail if someone tries to put an instance into a hash table ... rather than a mysterious performance black-hole. 这样,如果有人尝试将实例放入哈希表中,那么您将获得快速失败...而不是神秘的性能黑洞。 (I would NOT recommend returning a constant hashcode.) (我不建议返回常量哈希码。)

There is a related scenario where you might do this: when the object is inherently mutable, and you want to avoid the badness that happens if you mutate a hash key so that its hashcode changes. 在一个相关的场景中,您可以执行以下操作:当对象本质上是可变的,并且您希望避免在更改哈希键以使其哈希码发生更改时发生的不良情况。

If you're going to be concerned with either of these, you really, really should (need) to implement / override both. 如果您将要考虑这两种情况,那么您确实(确实)应该实现/覆盖两者。 See Why do I need to override the equals and hashCode methods in Java? 请参阅为什么需要重写Java中的equals和hashCode方法? for specifics, including what can happen if these aren't implemented with proper, related implementations. 具体细节,包括如果不采用适当的相关实现来实现,将会发生什么。

Additionally, from another answer there: 此外,从另一个答案那里:

You must override hashCode() in every class that overrides equals(). 您必须在每个覆盖equals()的类中覆盖hashCode()。 Failure to do so will result in a violation of the general contract for Object.hashCode(), which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable. 否则将导致违反Object.hashCode()的常规协定,这将阻止您的类与所有基于哈希的集合(包括HashMap,HashSet和Hashtable)一起正常运行。

from Effective Java, by Joshua Bloch 来自有效Java,作者Joshua Bloch

This method returns the hash code value for the object on which this method is invoked. 此方法返回在其上调用此方法的对象的哈希码值。 This method returns the hash code value as an integer and is supported for the benefit of hashing based collection classes such as Hashtable, HashMap, HashSet etc. This method must be overridden in every class that overrides the equals method. 此方法以整数形式返回哈希码值,并且支持基于哈希的收集类(例如Hashtable,HashMap,HashSet等)。此方法必须在覆盖equals方法的每个类中被覆盖。

reference 参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM