Означает ли равенство хэш-кода ссылку на равенство на основе ссылок? - PullRequest
3 голосов
/ 28 апреля 2011

Я читал, что для использования метода equals () в java мы также должны переопределить метод hashcode () и что у равных (логически) объектов должны быть действительные хеш-коды, но это не означает, что ссылкана основе равенства!Вот мой код для переопределенного метода equals (), как мне переопределить метод хеш-кода для этого:

@Override    
public boolean equals(Object o)
        {
            if (!(o instanceof dummy))
                return false;
            dummy p = (dummy) o;
            return (p.getName() == this.getName() && p.getId() == this.getId() && p.getPassword() == this.getPassword());

        } 

Я просто пытаюсь узнать, как он работает, поэтому есть только три поля, а именно name, id и пароль , и просто пытаюсь сравнить два объекта, которые я определяю в main (), вот и все!Мне также нужно знать, если всегда необходимо переопределить метод hashcode () вместе с методом equals ()?

Ответы [ 5 ]

5 голосов
/ 28 апреля 2011

Равенство хэш-кодов не означает ничего .Тем не менее, хеш-код неравенство должен подразумевать, что equals приведет к значению false, и любые два равных элемента всегда должны иметь одинаковый хеш-код.

По этой причине всегда разумно переопределятьхэш-код с равными, потому что ряд структур данных полагаются на него.

0 голосов
/ 28 апреля 2011

Даже если сбой переопределения hashCode() нарушит использование вашего класса только в HashSet, HashMap и других зависимых от hashCode структурах, вы все равно должны переопределить hashCode(), чтобы поддерживать контракт, описанный Object.

Общая стратегия большинства реализаций hashCode() состоит в объединении хэш-кодов полей, используемых для определения равенства. В вашем случае разумный hashCode() может выглядеть примерно так:

public int hashCode(){
    return this.getName().hashCode() ^ this.getId() ^ this.getPassword().hashCode();
}
0 голосов
/ 28 апреля 2011

Идея с hashCode() состоит в том, что это уникальное представление вашего объекта в данном пространстве. Структуры данных, в которых хранятся объекты, используют хэш-коды для определения места размещения объектов. В Java, например, HashSet использует хеш-код объекта, чтобы определить, в каком сегменте находятся эти объекты, а затем для всех объектов в этом сегменте он использует equals(), чтобы определить, является ли он матч.

Если вы не переопределяете hashCode(), но переопределяете equals(), то вы попадаете в точку, в которой 2 объекта считаются равными , равными , но коллекции Java не видят его так же. Это приведет к очень странному поведению.

0 голосов
/ 28 апреля 2011

Вам нужно переопределить hashCode(), когда вы переопределите equals().Простого использования equals() недостаточно, чтобы потребовать переопределения hashCode().

0 голосов
/ 28 апреля 2011

В вашем коде вы фактически не сравниваете значения своих полей. Используйте equals() вместо ==, чтобы сделать вашу реализацию равной.

return (p.getName().equals(this.getName()) && ...

(Обратите внимание, что приведенный выше код может вызвать исключение нулевой ссылки, если getName() возвращает ноль: вы можете использовать служебный класс, как описано здесь )

И да, hashCode() будет вызываться при использовании некоторой структуры данных хеширования, такой как HashMap, HashSet

Вы должны переопределять hashCode () в каждом класс, который переопределяет равно (). недостаточность это приведет к нарушению генеральный контракт на Object.hashCode (), который будет препятствовать ваш класс не работает должным образом в сочетании со всеми основанными на хэше коллекции, в том числе HashMap, HashSet и Hashtable.

из Эффективная Java , Джошуа Блох

См. Также

...