Створюючи свій власний об'єкт пари ключів, вам слід зіткнутися з кількома речами.
По-перше, ви повинні знати про впровадження 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()
також знайте, для чого це використовується, і будьте в курсі того, як ви створюєте свої ключі, оскільки вони є об'єктами. Часто ви робите непотрібне, якщо висловлювання викликають у вас завжди однаковий результат.
Якщо ви створюєте такі ключі: 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
на aKey
.
Якщо вам цікаво про фінал, я оголошую що-небудь як остаточне, значення якого встановлюється при інстанції і ніколи не змінюється - і тому є постійною об'єктом.