Ce face Object.equals
Implementarea din Object a lui equals compară identitatea: a.equals(b) este adevărat doar dacă a și b sunt același obiect, exact ca a == b. Clasele care reprezintă valori (String, Integer, LocalDate, records) o suprascriu ca să compare conținutul.
hashCode() returnează un int folosit de colecțiile cu hash pentru a găsi rapid un obiect. Regula de aur: dacă a.equals(b), atunci a.hashCode() == b.hashCode(). Când suprascrii equals, trebuie să suprascrii și hashCode (cel mai simplu cu Objects.hash); altfel HashSet și HashMap nu îți mai găsesc obiectele. Varianta implicită a lui hashCode diferă la fiecare rulare.
Un record primește automat equals și hashCode corecte, bazate pe toate componentele.
Parametri
| Parametru | Descriere |
|---|---|
obj |
Obiectul cu care se compară; poate fi null (rezultat false). |
Ce returnează
equals: boolean. hashCode: un int.
Exemple
Exemplul 1: Fără suprascriere: identitate
public class Main {
static class Oras {
final String nume;
Oras(String nume) {
this.nume = nume;
}
}
public static void main(String[] args) {
Oras a = new Oras("Iași");
Oras b = new Oras("Iași");
Oras c = a;
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(a.hashCode() == c.hashCode());
}
}
Rezultat
false
true
true
Exemplul 2: equals și hashCode suprascrise
Două produse cu același cod sunt egale, iar HashSet păstrează doar unul.
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public class Main {
static class Produs {
final String cod;
final String nume;
Produs(String cod, String nume) {
this.cod = cod;
this.nume = nume;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Produs p)) {
return false;
}
return cod.equals(p.cod);
}
@Override
public int hashCode() {
return Objects.hash(cod);
}
}
public static void main(String[] args) {
Produs a = new Produs("P-100", "Cafea");
Produs b = new Produs("P-100", "Cafea boabe");
System.out.println(a.equals(b));
System.out.println(a.hashCode() == b.hashCode());
Set<Produs> stoc = new HashSet<>();
stoc.add(a);
stoc.add(b);
System.out.println("Produse distincte: " + stoc.size());
System.out.println(a.equals(null));
}
}
Rezultat
true
true
Produse distincte: 1
false
Exemplul 3: Un record le are pe amândouă
import java.util.Set;
public class Main {
record Punct(int x, int y) {}
public static void main(String[] args) {
Punct p1 = new Punct(3, 4);
Punct p2 = new Punct(3, 4);
System.out.println(p1.equals(p2));
System.out.println(p1.hashCode() == p2.hashCode());
System.out.println(Set.of(p1).contains(p2));
}
}
Rezultat
true
true
true
Greșeli frecvente
- Suprascrii
equalscu parametrul de tip propriu:public boolean equals(Produs p)nu suprascrie, ci supraîncarcă metoda. Parametrul trebuie să fieObject; adnotarea@Overridete avertizează. - Suprascrii doar
equals, fărăhashCode: obiectele egale ajung în locuri diferite dinHashMapși nu se mai găsesc. - Folosești în
hashCodecâmpuri care se schimbă după ce obiectul a fost pus într-unHashSet: obiectul „se pierde” în set.
Comenzi înrudite
equals și hashCode: equals decide când două obiecte sunt „egale” ca valoare; hashCode trebuie rescris împreună cu el, altfel HashMap și HashSet nu funcționează corect.Objects.hash: hash() calculează un cod hash din mai multe câmpuri (ideal în hashCode()); hashCode(o) dă 0 pentru null.Objects: Clasa java.util.Objects are metode statice care lucrează sigur cu null; equals() compară două obiecte care pot fi null.Object: Clasa de bază a tuturor claselor Java; getClass() spune din ce clasă face parte un obiect la rulare.String.equals: Verifică dacă două șiruri au exact același text; equalsIgnoreCase și equalsFoldCase ignoră literele mari/mici.