Контракти Java equals() та hashCode() для семирічних дітей

Що таке equals() та hashCode() у Java?

Уявіть, що ви колекціонуєте картки Pokemon, на яких вказано номер та конкретного Покемона, наприклад, Charizard #006.

equals() — дві картки вважаються рівними, якщо у вас є дві однакові картки Charizard (вам пощастило!). Вони рівні, бо мають однаковий номер і того ж самого Покемона.

hashCode() — ви можете мати різні коробки для кожного Покемона. У нашому прикладі — дві картки Charizard можуть бути розміщені в одній коробці. Ця коробка має свій hashCode. Якщо вам потрібно швидко знайти картку Charizard, ви знатимете, яку коробку відкрити.

Контракт

  1. Якщо дві картки рівні, вони повинні мати однаковий hashCode — кожна картка Charizard буде в одній і тій самій коробці.
  2. Якщо дві картки мають різні hashCode, то вони повинні бути різними (різні Покемони, різні коробки). Іноді трапляється, що різні hashCode знаходяться в одній коробці, але це трапляється дуже рідко.

Якщо дві картки рівні — вони мають однаковий hashCode.

Якщо дві картки різні — вони матимуть різні hashCode (зазвичай).

Порушення контракту

  1. Помилки в колекціях (наприклад, HashMap, HashSet) — якщо ви покладете Charizard у коробку №69, ви ніколи не знайдете його у коробці №6.
  2. Інші помилки — якщо метод 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)

Leave a Reply

Your email address will not be published. Required fields are marked *