3

There is some code in java.util.HashMap.TreeNode#putTreeVal(), just like below:

if ((ph = p.hash) > h)
    dir = -1;
else if (ph < h)
    dir = 1;
else if ((pk = p.key) == k || (k != null && k.equals(pk)))
    return p;
else if ((kc == null &&
          (kc = comparableClassFor(k)) == null) ||
         (dir = compareComparables(kc, k, pk)) == 0) {
    if (!searched) {
        TreeNode<K,V> q, ch;
        searched = true;
        if (((ch = p.left) != null &&
             (q = ch.find(h, k, kc)) != null) ||
            ((ch = p.right) != null &&
             (q = ch.find(h, k, kc)) != null))
            return q;
    }
    dir = tieBreakOrder(k, pk);
}

There have two situation: h less than ph, h greater than ph. Usually, the code (pk = p.key) == k || (k != null && k.equals(pk)) means h equals to ph, but i don't know why there still else if after that.

What is the situation when two objects's hashCode is equals to each other, but == and euqlas() will get false?

When Object's class override equals() method will cause this situation? But i used heard that override equals() must override hashCode() too, so this question wouldn't happen to.

I hope some people could tell me which situation will cause the third else if.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
shengbang he
  • 128
  • 9
  • 3
    "What is the situation when two objects's hashCode is equals to each other, but == and euqlas() will get false?" - any time there's a hash collision. Two objects having the same hash code means they *might* be equal, not that they *are* equal. There are only 2^32 possible values from `hashCode()`, but far more than 2^32 possible strings, for example - so there *must* be strings that have the same hash code, but aren't equal. – Jon Skeet Jan 19 '19 at 09:14
  • From the documentation: "It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables." – Jon Skeet Jan 19 '19 at 09:15
  • [Are two Java objects with same hashcodes not necessarily equal? - Stack Overflow](https://stackoverflow.com/questions/5443136/are-two-java-objects-with-same-hashcodes-not-necessarily-equal) – user202729 Jan 19 '19 at 09:16
  • Thank you @JonSkeet, you got the point. I ignored hash collision, i knew that different objects may have same hashCode but didn't have profound understanding and apply it to HashMap. – shengbang he Jan 19 '19 at 14:18

2 Answers2

2

What is the situation when two objects's hashCode is equals to each other, but == and equals() will get false?

According to Java Documentation:

  • If objects are equal (i.e. x.equals(y) == true), then hashCode of these object should also be equal (i.e. x.hashCode() == y.hashCode())
  • If two objects with equal hashCode (i.e. x.hashCode() == y.hashCode()), then there's not mandatory for these objects to be equal (i.e. x.equals(y) == true/false)

See details in Oracle Java Tutorial: Object as a Superclass

PranshuKhandal
  • 739
  • 7
  • 19
Oleg Cherednik
  • 17,377
  • 4
  • 21
  • 35
1

What is the situation when two objects's hashCode is equals to each other, but == and equals() will get false ?

When a hashcode collision occurs.

Example

Consider those two Longs:

Long l1 = 1L;
Long l2 = 4294967296L; //which is 2 ^ 32

Do you agree that there are different and equals() will return false? However, the result of

l1.hashCode() == l2.hashCode()

is true.

Why? Look at the implementation of hashCode for Long:

public static int hashCode(long value) {
    return (int)(value ^ (value >>> 32));
}

Since a long can have 2^64 values and the return value of hashcode is a int which can have 2^32 values, it is normal that you have collisions (each value makes collisions with 2^32 other values).


Clarifications

But i used heard that override equals() must override hashCode() too, so this question wouldn't happen to.

Yes, when you override equals() you should override hashCode() too. This is true but I think you mixed up the implications. From the javadoc of hashcode:

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 hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So the implication

a.equals(b) => a.hashCode() == b.hashCode()

has to be always true (if your methods are correctly implemented) but the converse implication

a.hashCode() == b.hashCode() => a.equals(b)

doesn't necessarily have to.

Ricola
  • 2,621
  • 12
  • 22