Java: Use hashCode() inside of equals() for conven

2019-01-14 12:15发布

Consider the following test case, is it a bad practice to use the hashCode() method inside of equals as a convenient shortcut?

public class Test 
{    
    public static void main(String[] args){
        Test t1 = new Test(1, 2.0, 3, new Integer(4));
        Test t2 = new Test(1, 2.0, 3, new Integer(4));
        System.out.println(t1.hashCode() + "\r\n"+t2.hashCode());
        System.out.println("t1.equals(t2) ? "+ t1.equals(t2));
    }

    private int myInt;
    private double myDouble;
    private long myLong;
    private Integer myIntObj;

    public Test(int i, double d, long l, Integer intObj ){
        this.myInt = i;
        this.myDouble = d;
        this.myLong = l;
        this.myIntObj = intObj;
    }

    @Override
    public boolean equals(Object other)
    {        
        if(other == null) return false;
        if (getClass() != other.getClass()) return false;            

        return this.hashCode() == ((Test)other).hashCode();//Convenient shortcut?
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 53 * hash + this.myInt;
        hash = 53 * hash + (int) (Double.doubleToLongBits(this.myDouble) ^ (Double.doubleToLongBits(this.myDouble) >>> 32));
        hash = 53 * hash + (int) (this.myLong ^ (this.myLong >>> 32));
        hash = 53 * hash + (this.myIntObj != null ? this.myIntObj.hashCode() : 0);
        return hash;
    }   
}

Output from main method:

1097562307
1097562307
t1.equals(t2) ? true

7条回答
Luminary・发光体
2楼-- · 2019-01-14 12:48

Bad practice? More than that, it's completely wrong. Two un-equal objects can return the same hash code. Do not do this.

查看更多
放荡不羁爱自由
3楼-- · 2019-01-14 12:51

This is not OK. Hashcodes, by their very nature, are not guaranteed to be unique.

查看更多
贪生不怕死
4楼-- · 2019-01-14 12:54

In general, it's not at all safe to compare the hashCode() instead of using equals(). When equals() returns false, hashCode() may return the same value, per the contract of hashCode().

查看更多
我只想做你的唯一
5楼-- · 2019-01-14 13:05

As all other answers state this is bad practice. However, one situation where you might want to refer to the hash code within the equals method is in cases where you have an immutable object and have cached the hash code previously. This allows you to perform a cheap inexact comparison before performing a full comparison. For example:

public class MyImmutable {
    private final String a;
    private final String b;
    private final int c;

    private int hashCode;

    public MyImmutable(String a, String b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MyImmutable that = (MyImmutable) o;

        // Compare cached hashCodes first before performing more expensive comparison.
        return hashCode == that.hashCode() && c == that.c && !(a != null ? !a.equals(that.a) : that.a != null) && !(b != null ? !b.equals(that.b) : that.b != null);
    }

    @Override
    public int hashCode() {
        if (hashCode == 0) {
            // hashCode not cached, or it was computed as 0 (we recalculate it in this case).
            hashCode = a != null ? a.hashCode() : 0;
            hashCode = 31 * hashCode + (b != null ? b.hashCode() : 0);
            hashCode = 31 * hashCode + c;
        }

        return hashCode;
    }
}
查看更多
虎瘦雄心在
6楼-- · 2019-01-14 13:10

Here is the contract, copied from the Object specification [JavaSE6]:

It is not required that if two objects are unequal according to the equals(Ob- ject) 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.

To answer your question, No. Not a good idea.

查看更多
唯我独甜
7楼-- · 2019-01-14 13:12

As Ryan Stewart says, your code as written is faulty.

A situation in which it might be useful to use the hash-code of your objects in equals() is when your object caches the hash codes, and determining equality is portentially expensive. In that case you might use equality of the cached hash codes as one of the early necesssary-but-not-sufficient checks for equality, to return false fast for most pairs of objects that are not equals().

查看更多
登录 后发表回答