简体   繁体   中英

Why should two equal objects return equal hash codes if I don't want to use my object as a key in a hash table?

This is what the Java documentation of Object.hashCode() says:

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

But they don't explain why two equal objects must return equal hash codes. Why did Oracle engineers decided hashCode must be overriden when overriding equals ?

The typical implementation of equals doesn't call the hashCode method:

@Override
public boolean equals(Object arg0) {
    if (this == arg0) {
        return true;
    }
    if (!(arg0 instanceof MyClass)) {
        return false;
    }
    MyClass another = (MyClass) arg0;
    // compare significant fields here
}

In Effective Java (2nd Edition) I read:

Item 9: Always override hashCode when you override equals.

A common source of bugs is the failure to override the hashCode method. You must override hashCode in every class that overrides equals. 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.

Suppose I don't need to use MyClass as a key of a hash table. Why do I need to override hashCode() in this case?

Of course when you have a little program only written by your self and you check every time you use an external lib that this did not rely on hashCode() then you can ignore all this warnings. But when a software projects grows you will use external libraries and and these will rely on hashCode() and you will lose a lot of time searching for bugs. Or in a newer Java version some other classes use the hashCode() too and your program will fail.

So its a lot easier to just implement this and follow this easy rule, because an modern IDE can auto generate equals and hashCode with one click.

Update a little story : At work we ignored this rule too in a lot of classes and only implemented the one needed mostly equals or compareTo . Some day some strange things happen, because one programmer has used a Hash*-Class in the GUI and our Objects did not follow this rule. In the end an apprentice need to search all classes with equals and have to add the corresponding hashCode method.

As the text says, it's a violation of the general contract that is in use. Of course if you never ever use it in any place that hashCode would be required nobody is forcing you to implement it.

But what if some day in the future it is needed? What if the class is used by some other developer? That's why there is this contract that both of them have to be implemented, so there is no confusion.

Obviously if nobody ever calls your class's hashCode method, nobody will know that it's inconsistent with equals . Can you guarantee that for the duration of your project, including the years in maintenance, no one will need to, say, remove duplicate objects from a list or associate some extra bit of data with your objects?

You are probably just safer implementing hashCode so that it's consistent with equals. It's not particularly hard, always returning 0 is already a valid implementation.

(please don't just return 0 though)

The reason why hashCode has to be overridden to agree with equals is because of why and how hashCode is used. Hash codes are used as surrogates for values so that when mapping a key value to something hashing can be used to give near-constant lookup time with reasonable space. When two values compare equal (ie, they are the same value) then they have to map to the same something when used as a key for a hashed collection. That requires that they have the same hash code to get them there.

You have to override hashCode appropriately because the manual says you have to. It says you have to because the decision was made that libraries can assume that you are satisfying that contract so they (& you) can have the performance benefits of hashing when using a value that you gave it as a key in their functions' implementations.

The common wizdom dictates that the logic for // compare significant fields here is required for equals() and also for compareTo() (in case you want to sort instances of MyClass ) and also for using hash tables. so it makes sense to put this logic in hashCode() and have the other methods use the hash code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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