Когда вы создаете свой собственный объект пары ключей, вы должны столкнуться с некоторыми проблемами.
Во-первых, вы должны знать о реализации hashCode()
и equals()
. Вам нужно будет это сделать.
Во-вторых, при внедрении hashCode()
убедитесь, что вы понимаете, как это работает. Данный пример пользователя
public int hashCode() {
return this.x ^ this.y;
}
на самом деле одна из худших реализаций, которые вы можете сделать. Причина проста: у вас много одинаковых хешей! И hashCode()
должен возвращать значения типа int, которые, как правило, бывают редкими, в лучшем случае уникальными. Используйте что-то вроде этого:
public int hashCode() {
return (X << 16) + Y;
}
Это быстро и возвращает уникальные хэши для ключей от -2 ^ 16 до 2 ^ 16-1 (от -65536 до 65535). Это подходит практически в любом случае. Очень редко вы выходите за эти границы.
В-третьих, при реализации equals()
также знайте, для чего он используется, и знайте, как вы создаете свои ключи, поскольку они являются объектами. Часто вы делаете ненужные инструкции if, потому что у вас всегда будет один и тот же результат.
Если вы создаете такие ключи: map.put(new Key(x,y),V);
вы никогда не сравните ссылки на свои ключи. Потому что каждый раз, когда вы хотите получить доступ к карте, вы будете делать что-то вроде map.get(new Key(x,y));
. Поэтому вам equals()
не нужно утверждение вроде if (this == obj)
. Этого никогда не будет .
Вместо того , чтобы if (getClass() != obj.getClass())
в вашем equals()
лучшем использовании if (!(obj instanceof this))
. Это будет справедливо даже для подклассов.
Итак, единственное, что вам нужно сравнить, это на самом деле X и Y. Итак, лучшая equals()
реализация в этом случае будет:
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
Итак, в итоге ваш ключевой класс выглядит так:
public class Key {
public final int X;
public final int Y;
public Key(final int X, final int Y) {
this.X = X;
this.Y = Y;
}
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
public int hashCode() {
return (X << 16) + Y;
}
}
Вы можете указать свои индексы измерения X
и Y
уровень публичного доступа, поскольку они являются окончательными и не содержат конфиденциальной информации. Я не уверен на 100%, правильно ли private
работает уровень доступа в любом случае при приведении Object
к файлу Key
.
Если вас интересует финал, я объявляю все окончательным, значение которого устанавливается при создании экземпляра и никогда не изменяется - и поэтому является константой объекта.