8

If two objects return same hashCode, doesn't it mean that they are equal? Or we need equals to prevent collisions?

And can I implement equals by comparing hashCodes?

Zhambul
  • 942
  • 9
  • 23
  • 3
    Possible duplicate of [Is this equals legal?](http://stackoverflow.com/questions/42689905/is-this-equals-legal) – Hulk Mar 16 '17 at 11:49

7 Answers7

21

If two objects have the same hashCode then they are NOT necessarily equal. Otherwise you will have discovered the perfect hash function. But the opposite is true - if the objects are equal, then they must have the same hashCode.

shmakova
  • 6,076
  • 3
  • 28
  • 44
9

hashCode and Equals are different information about objects

Consider the analogy to Persons where hashcode is the Birthday,

in that escenario, you and many other people have the same b-day (same hashcode), all you are not the same person however..

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
3

The hashCode method as stated in the Oracle Docs is a numeric representation of an object in Java. This hash code has limited possible values (represented by the values which can be stored in an int).

For a more complex class, there is a high possibility that you will find two different objects which have the same hash code value. Also, no one stops you from doing this inside any class.

class Test {

    @Override
    public int hashCode() {
        return 0;
    }

}

So, it is not recommended to implement the equals method by comparing hash codes. You should use them for comparison only if you can guarantee that each object has an unique hash code. In most cases, your only certainty is that if two objects are equal using o1.equals(o2) then o1.hashCode() == o2.hashCode().

In the equals method you can define a more complex logic for comparing two objects of the same class.

Valy
  • 573
  • 2
  • 12
  • I consider it very helpful for a better understanding of the hashCode()-equals()-relation to know that also a hashCode() implementation always returning 0 is perfectly valid in regards of its general contract. Unfortunately all the helpful information is spread over different answers here. – Markus Benko Mar 16 '17 at 21:08
  • Yes, there is useful information spread around the answers here, but it is pretty hard to condense everything about hashCode() and equals() in a single answer :D. – Valy Mar 17 '17 at 11:03
3

If two objects return same hashCode, doesn't it mean that they are equal?

No it doesn't mean that.

The javadocs for Object state this:

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. ...
  • 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.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCodemethod on each of the two objects must produce distinct integer results. ...

Note the highlighted statement. It plainly says "No" to your question.


There is another way to look at this.

  1. The hashCode returns an int.
  2. There are only 232 distinct values that an int can take.
  3. If a.hashCode() == b.hashCode() implies a.equals(b), then there can be only 232 distinct (i.e. mutually unequal) objects at any given time in a running Java application.

That last point is plainly not true. Indeed, it is demonstrably not true if you have a large enough heap to hold 232 instances of java.lang.Object ... in a 64-bit JVM.


And a third way is to some well-known examples where two different two character strings have the same hashcode.


Given that your assumption is incorrect, the reasoning that follows from it is also incorrect.

  1. Java does need an equals method.
  2. You generally cannot implement equals using just hashCode.

You may be able to use hashCode to implement a faster equals method, but only if calling hashCode twice is faster than comparing two objects. It generally isn't.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
3

Why does Java need equals() if there is hashCode()?

Java needs equals() because it is the method through which object equality is tested by examining classes, fields, and other conditions the designer considers to be part of an equality test.

The purpose of hashCode() is to provide a hash value primarily for use by hash tables; though it can also be used for other purposes. The value returned is based on an object's fields and hash codes of its composite and/or aggregate objects. The method does not take into account the class or type of object.

The relationship between equals() and hashCode() is an implication.

  • Two objects that are equal implies that the have the same hash code.
  • Two objects having the same hash code does not imply that they are equal.

The latter does not hold for several reasons:

  • There is a chance that two distinct objects may return the same hash code. Keep in mind that a hash value folds information from a large amount of data into a smaller number.
  • Two objects from different classes with similar fields will most likely use the same type of hash function, and return equal hash values; yet, they are not the same.
  • hashCode() can be implementation-specific returning different values on different JVMs or JVM target installations.

Within the same JVM, hashCode() can be used as a cheap precursor for equality by testing for a known hash code first and only if the same testing actual equality; provided that the equality test is significantly more expensive than generating a hash code.

And can I implement equals by comparing hashCodes?

No. As mentioned, equal hash codes does not imply equal objects.

Frelling
  • 3,287
  • 24
  • 27
2

hashCodes are equal -> Objects might be equal -> further comparision is required
hashCodes are different -> Object are not equal (if hashCode is implemented right)

That's how equals method are implemented. At first you check if hashCodes are equal. If yes, you need to check class fields to see if it represents the exact same object. If hashCodes are different, you can be sure that objects are not equal.

szcz
  • 21
  • 2
1

Sometimes (very often?) you don't!

These answers are not untrue. But they don't tell the whole story.

One example would be where you are creating a load of objects of class SomeClass, and each instance that is created is given a unique ID by incrementing a static variable, nInstanceCount, or some such, in the constructor:

iD = nInstanceCount++;

Your hash function could then be

int hashCode(){
    return iD;
}

and your equals could then be

boolean equals( Object obj ){
    if( ! ( obj instanceof SomeClass )){
        return false;
    }
    return hashCode() == obj.hashCode();
}

... under such circumstances your idea that "equals is superfluous" is effectively true: if all classes behaved like this, Java 10 (or Java 23) might say, ah, let's just get rid of silly old equals, what's the point? (NB backwards compatibility would then go out the window).

There are two essential points:

  • you couldn't then create more than MAXINT instances of SomeClass. Or... you could ... if you set up a system for reassigning the IDs of previously destroyed instances. IDs are typically long rather than int ... but this wouldn't work because hashCode() returns int.

  • none of these objects could then be "equal" to another one, since equality = identity for this particular class, as you have defined it. Often this is desirable. Often it shuts off whole avenues of possibilities...

The necessary implication of your question is, perhaps, what's the use of these two methods which, in a rather annoying way, have to "cooperate"? Frelling, in his/her answer, alluded to the crucial point: hash codes are needed for sorting into "buckets" with classes like HashMap. It's well worth reading up on this: the amount of advanced maths that has gone into designing efficient "bucket" mechanisms for classes like HashMap is quite frightening. After reading up on it you may come to have (like me) a bit of understanding and reverence about how and why you should bother implementing hashCode() with a bit of thought!

mike rodent
  • 14,126
  • 11
  • 103
  • 157