Создание метода hashCode() - Java
У меня возникли проблемы с написанием метода hashCode()
для созданного мной класса. Этот класс предназначен для использования внутри TreeSet, и, таким образом, он реализует Comparable. Класс имеет следующие переменные:
public class Node implements Comparable<Node> {
Matrix matrix;
int[] coordinates= new int[2];
Node father;
int depth;
int cost;
Здесь выполняется реализация метода compareTo()
. Я хочу, чтобы TreeSet
организовал эти структуры Node по их стоимости, поэтому compareTo()
возвращает результат простого вычитания.
public int compareTo(Node nodeToCompare) {
return this.cost - nodeToCompare.cost;
}
Я также реализовал метод equals()
.
public boolean equals(Object objectToCompare) {
if(objectToCompare== this) {return true;}
if(objectToCompare== null || objectToCompare.getClass()!= this.getClass()) {return false;}
Node objectNode= (Node) objectToCompare;
return this.father.equals(objectNode.father) &&
this.depth== objectNode.depth &&
this.cost== objectNode.cost &&
this.matrix.equals(objectNode.matrix) &&
Arrays.equals(this.coordinates, objectNode.coordinates);
}
Сказав все это, у меня есть несколько вопросов:
- Поскольку я реализовал новый метод
equals()
, должен ли я реализовать новый метод hashCode()
?
- Как я могу реализовать новый хэш-код
method()
с этими переменными? (Обратите внимание, что переменная матрица типа Matrix имеет реализованный метод hashCode()
)
Что все!
Ответы
Ответ 1
Ваш метод compareTo
не согласуется с вашим методом equals
: ваш метод compareTo
говорит, что два экземпляра эквивалентны, если они имеют одинаковый cost
— такой, что a TreeSet
может содержать только не более одного экземпляра с данным cost
— но ваш метод equals
говорит, что они эквивалентны, если они имеют один и тот же cost
и одинаковы с другими способами.
Итак, предположим, что ваш метод equals
верен:
Ответ 2
Intellij IDEA может сделать это как функцию "правой кнопки мыши". Просто увидев, что это сделано правильно, вы научите вас много.
И вы должны переопределить оба в любом случае.
Ответ 3
В контракте для метода hashCode указано, что если два объекта равны, то вызов hashCode() должен дать вам тот же целочисленный результат. Противоположность не должна быть истинной, т.е. Если два хэш-кода одинаковы, объекты не должны равняться друг другу.
Глядя на ваш метод equals (который требует переменный перевод btw), вы можете добавить хэш-коды всех внутренних переменных-членов, которые должны быть равны для вашего метода equals, чтобы дать true. например.
public int hashCode() {
return this.matrix.hashCode() +
this.coordinates[0] +
this.coordinates[1] +
this.father.hashCode() +
this.depth + this.cost;
}
Вышеприведенное предполагает, что матрица и отец никогда не являются нулями, вам нужно убедиться, что вы проверяете нули, если это не так.
Если вы чувствуете себя более предприимчивыми, вы можете размножить несколько из вышеперечисленных с простым, чтобы убедиться, что вы не получаете столкновений hashCode для разных данных (это поможет повысить производительность, если вы используете свой класс в хэш-таблицах и хэш-картах). Если вам нужно обслуживать нули, описанный выше метод может быть написан немного лучше:
public int hashCode() {
return ((this.matrix == null) ? 0 : this.matrix.hashCode()) +
17 * this.coordinates[0] +
this.coordinates[1] +
((this.father == null) ? 0 : this.father.hashCode()) +
31 * this.depth + 19 * this.cost;
}
Ответ 4
Если ваша коллекция мала, вы можете вернуть константу из метода hashCode. Он используется для быстрого поиска. hashCodes походит на блоки, в которых хранятся элементы. Правила:
- Равные элементы должны быть в одной коробке (имеют один и тот же hashCode) - конечно;
- Не равные элементы могут быть как в одном, так и в разных блоках.
Затем вы возвращаете константу, вы подчиняетесь этим двум правилам, но это может значительно снизить производительность на небольших списках (поскольку JVM будет искать во всех элементах, а не только в элементах в одной и той же коробке). Но обратная константа - плохой подход.
PS: Извините за мое письмо. Английский не мой родной язык.
PPS: обычно вы должны реализовать метод hashCode таким же образом, как equals (использовать те же элементы)