Я понимаю, почему важно обеспечить одинаковый хэш-код для двух одинаковых (через equals
) объектов. Но верно ли и наоборот, если два объекта имеют одинаковый хэш-код, они должны быть равны? Договор сохраняется? Я не могу найти пример, где это может произойти, потому что если все атрибуты, принимающие участие в методе equals, используются для переопределения метода hashcode, то мы всегда будем иметь один и тот же хэш-код объектов, которые равны. Прокомментируйте.
Являются ли два Java-объекта с одинаковыми хэш-кодами не обязательно равными?
Ответ 1
Если два объекта имеют одинаковый hashcode
, то они НЕ обязательно равны. В противном случае вы обнаружите идеальную хеш-функцию.
Но верно и обратное: если объекты равны, то они должны быть одинаковыми hashcode
.
Ответ 2
Назначение функции hashCode
позволяет быстро разбить объекты на множества вещей, которые, как известно, не равны всем элементам вне их собственного набора. Предположим, что у одного есть 1000 предметов, и один делит их на десять наборов грубо одинакового размера. Один вызов hashCode
мог бы быстро идентифицировать элемент как не равный 900 элементам, без необходимости использовать equals
для любого из этих элементов. Даже если нужно было использовать equals
для сравнения элемента со 100 другими элементами, это все равно будет только 1/10 стоимости сравнения его со всеми 1000 элементами. На практике даже в большой коллекции hashCode
часто устраняет 99,9% или более неравных предметов, оставляя, как минимум, небольшую часть, подлежащую исследованию.
Ответ 3
Согласно Javadoc в: http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode%28%29
Не требуется, чтобы, если два объекта были неравны в соответствии с методом equals (java.lang.Object), то вызов метода hashCode для каждого из двух объектов должен приводить к разным целочисленным результатам. Тем не менее, программист должен знать, что выдача различных целочисленных результатов для неравных объектов может повысить производительность хеш-таблиц.
Изменение: В реальном мире две строки могут иметь одинаковый хэш-код. Например, если вы хотите сохранить все строковые комбинации, которые содержат строчные английские буквы (например, "aaaaaaaaaa", "aaaaaaaaab" и т.д.) Длиной 10, вы не можете назначить уникальный хэш-код каждому из 141.167.095.653. 376 комбинаций, поскольку int в Java является 32-битным и, следовательно, может иметь до 4,294,967,296 различных значений.
Ответ 4
Фактически
public int hashCode(){
return 1;
}
Является действительной реализацией hashcode... но ужасной. Будет делать все ваши хеш-таблицы медленными. Но да, у вас могут быть два разных объекта с одним и тем же хэш-кодом. Но это не должно быть общим случаем, реальная реализация должна давать разные хэш-коды для разных значений большую часть времени.
Ответ 5
Любопытно, что NumberFormat является примером базового класса Java, который нарушает рекомендацию:
Насколько это разумно практично, метод hashCode, определяемый class Object возвращает разные целые числа для разных объектов.
Вот пример, показывающий это, по крайней мере, под версией Java, которую я сейчас запускаю под Mac OS X 10.6.
Numberformat nf = NumberFormat.getNumberInstance();
NumberFormat nf2 = NumberFormat.getNumberInstance();
assert nf != nf2; // passes -- they are different objects
assert !nf.equals(nf2); // passes -- they are not equal
assert nf.hashCode() != nf2.hashCode(); // fails -- same hash code
Ответ 6
Значение hashCode
зависит от реализации. например, String
класс реализует функцию hashCode()
в зависимости от значения. это означает
String a=new String("b");
String b=new String("b");
будет иметь тот же hashCode
, но это два разных объекта. и a==b
вернется false
.
Ответ 7
Метод хэш-кода возвращает целое число. Если диапазон целых чисел заканчивается, то и два разных объекта будут иметь один и тот же хэш-код. Поэтому нет необходимости, чтобы два разных объекта имели одинаковый хеш-код.
Ответ 8
Чтобы доказать, что если два объекта имеют одинаковые hashCode не означает, что они равны
Скажем, у вас есть два пользовательских класса
class Object1{
private final int hashCode = 21;
public int hashCode(){
return hashCode;
}
public boolean equals(Object obj) {
return (this == obj);
}
}
class Object2{
private final int hashCode = 21;
public int hashCode(){
return hashCode;
}
public boolean equals(Object obj) {
return (this == obj);
}
}
Object1 object1 = new Object1();
Object2 object2 = new Object2();
Object1 object3 = new Object1();
if(object1.hashCode() == object2.hashCode()){
// return true, because the hashcodes are same
}
but
if(object1.equals(object3)){
// will fail, because two different objects
}
Ответ 9
hashcode() возвращает уникальный целочисленный идентификатор для каждого объекта. Если хеш-код объекта не совпадает с хеш-кодом другого объекта, нет смысла выполнять метод equals(): вы просто знаете, что два объекта не совпадают. С другой стороны, если хеш-код одинаков, необходимо выполнить метод equals(), чтобы определить, совпадают ли значения и поля.