Що таке equals() та hashCode() у Java?
Уявіть, що ви колекціонуєте картки Pokemon, на яких вказано номер та конкретного Покемона, наприклад, Charizard #006.
equals() — дві картки вважаються рівними, якщо у вас є дві однакові картки Charizard (вам пощастило!). Вони рівні, бо мають однаковий номер і того ж самого Покемона.
hashCode() — ви можете мати різні коробки для кожного Покемона. У нашому прикладі — дві картки Charizard можуть бути розміщені в одній коробці. Ця коробка має свій hashCode. Якщо вам потрібно швидко знайти картку Charizard, ви знатимете, яку коробку відкрити.
Контракт
- Якщо дві картки рівні, вони повинні мати однаковий hashCode — кожна картка Charizard буде в одній і тій самій коробці.
- Якщо дві картки мають різні hashCode, то вони повинні бути різними (різні Покемони, різні коробки). Іноді трапляється, що різні hashCode знаходяться в одній коробці, але це трапляється дуже рідко.
Якщо дві картки рівні — вони мають однаковий hashCode.
Якщо дві картки різні — вони матимуть різні hashCode (зазвичай).
Порушення контракту
- Помилки в колекціях (наприклад, HashMap, HashSet) — якщо ви покладете Charizard у коробку №69, ви ніколи не знайдете його у коробці №6.
- Інші помилки — якщо метод equals визначить, що дві картки з різними hashCode є рівними, це призведе до повного хаосу.
Приклад
java.util.Objects;
public class PokemonCard {
private String name;
private int number;
public PokemonCard(String name, int number) {
this.name = name;
this.number = number;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PokemonCard that = (PokemonCard) o;
return number == that.number && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name, number);
}
@Override
public String toString() {
return name + " #" + number;
}
public static void main(String[] args) {
PokemonCard pikachu1 = new PokemonCard("Pikachu", 25);
PokemonCard pikachu2 = new PokemonCard("Pikachu", 25);
PokemonCard charizard = new PokemonCard("Charizard", 6);
System.out.println("pikachu1.equals(pikachu2): " + pikachu1.equals(pikachu2)); // true
System.out.println("pikachu1.equals(charizard): " + pikachu1.equals(charizard)); // false
System.out.println("pikachu1.hashCode(): " + pikachu1.hashCode());
System.out.println("pikachu2.hashCode(): " + pikachu2.hashCode());
System.out.println("charizard.hashCode(): " + charizard.hashCode());
}
}
Перекладено з: [Java equals() and hashCode() contracts for 7 years old](https://medium.com/@ron.monika/java-equals-and-hashcode-contracts-for-7-years-old-ddd9466bf9bb)