Ответ 1
В общем, это не совсем безопасно сравнивать hashCode() вместо использования equals(). Когда equals() возвращает false, hashCode() может возвращать одно и то же значение на контракт hashCode().
Рассмотрим следующий тестовый пример: неудобно ли использовать метод hashCode() внутри равных как удобный ярлык?
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;
}
}
Выход из основного метода:
1097562307
1097562307
t1.equals(t2) ? true
В общем, это не совсем безопасно сравнивать hashCode() вместо использования equals(). Когда equals() возвращает false, hashCode() может возвращать одно и то же значение на контракт hashCode().
Очень плохо! Равномерность HashCode не означает, что equals возвращает true. Контракт состоит в том, что два одинаковых объекта должны иметь одинаковый хэш-код. Но это НЕ означает, что два объекта с одним и тем же HashCode должны быть равны.
Это не нормально. Хаскоды по самой своей природе не гарантированы быть уникальными.
Как все остальные ответы говорят, что это плохая практика. Однако, одна из ситуаций, когда вы можете захотеть ссылаться на хеш-код в методе equals, - в тех случаях, когда вы имеете неизменяемый объект и кэшировали хеш-код ранее. Это позволяет выполнить дешевое неточное сравнение перед выполнением полного сравнения. Например:
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;
}
}
Плохая практика? Более того, это совершенно неправильно. Два неравных объекта могут возвращать один и тот же хэш-код. Не делайте этого.
Вот контракт, скопированный из спецификации объекта [JavaSE6]:
Не требуется, чтобы два объекта были неравными по equals (Object), затем вызывая метод hashCode на каждом из эти два объекта должны производить различные целочисленные результаты. Однако программист должен знать, что при создании отдельных целочисленных результатов для неравных объектов может улучшить производительность хеш-таблиц.
Чтобы ответить на ваш вопрос, нет. Не очень хорошая идея.
Как Райан Стюарт говорит, что ваш код, как написано, неисправен.
Ситуация, в которой было бы полезно использовать хэш-код ваших объектов в equals()
, - это когда ваш объект кэширует хэш-коды, а определение равенства является дорогостоящим. В этом случае вы можете использовать равенство кэшированных хеш-кодов в качестве одной из ранних необходимых, но не достаточных проверок равенства, чтобы вернуть false
быстро для большинства пар объектов, которые не являются equals()
.