Middle
Povedzte o zmluve metód hashCode a equals v Jave.
sobes.tech AI
Odpoveď od AI
Dohoda metód hashCode a equals v Jave určuje ich vzťah a zabezpečuje správne správanie objektov pri používaní kolekcií založených na hash tabuľkách (napríklad HashSet, HashMap).
Hlavné pravidlá dohody:
- Reflexivita: Pre akúkoľvek nenulovú referenciu
xmusíx.equals(x)vracaťtrue. - Symetria: Pre akékoľvek nenulové referencie
xaymusí platiť, žex.equals(y)vraciatrueak a len aky.equals(x)vraciatrue. - Transitivita: Pre akékoľvek nenulové referencie
x,yaz, akx.equals(y)ay.equals(z)sútrue, potomx.equals(z)musí byťtrue. - Konzistentnosť: Pre akékoľvek nenulové referencie
xay, opakované volaniex.equals(y)pri rovnakých objektoch musí vždy vracať rovnaký výsledok. - Null: Pre akúkoľvek nenulovú referenciu
x,x.equals(null)musí vracaťfalse.
A hlavné pravidlo spájajúce hashCode a equals:
- Ak sú dva objekty rovné podľa metódy
equals(Object), potom volaniehashCode()na každom z týchto objektov musí produkovať rovnaké celé číslo. - Opak je ne-pravdivý: ak majú dva objekty rovnaký hash kód, neznamená to, že sú rovnaké.
Hodnota dohody:
Porušenie dohody môže viesť k nesprávnemu správaniu kolekcií. Napríklad, ak dva rovné objekty vracajú odlišné hash kódy, HashMap ich môže umiestniť do rôznych "košov" a nebude ich vedieť nájsť podľa druhého, aj keď sú logicky rovnaké.
Príklad správnej implementácie:
// Príklad triedy so správnymi `equals` a `hashCode`
public final class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return x == point.x && y == point.y;
}
@Override
public int hashCode() {
int result = 17; // Magické číslo, zvyčajne prvočíslo
result = 31 * result + x;
result = 31 * result + y;
return result;
}
// Gettery (nepovinné pre `equals`/`hashCode`)
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Použitie:
- Vždy prepísať obe metódy (
equalsahashCode) spolu. - Pri výpočte
hashCodepoužívať tie isté polia, ktoré sa používajú vequals. - Snažiť sa vytvárať "dobré" hash funkcie, ktoré rovnomerne rozdeľujú hash kódy, aby minimalizovali kolízie (keď rôzne objekty majú rovnaký hash kód) a zlepšili výkon hashovaných kolekcií.
- Pre primitívy používať ich hodnoty. Pre objekty volať ich
hashCode(). Pre polia používať metódy zArrays.
V Java 7+ je odporúčané používať Objects.equals(Object a, Object b) a Objects.hash(Object... values) pre jednoduchšiu a správnu implementáciu.
Príklad s Objects:
// Príklad triedy s `equals` a `hashCode` s použitím `Objects`
import java.util.Objects;
public final class PointWithObjects {
private final int x;
private final int y;
public PointWithObjects(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PointWithObjects that = (PointWithObjects) o;
return x == that.x && y == that.y; // Logika porovnania ostáva
}
@Override
public int hashCode() {
return Objects.hash(x, y); // Pohodlná metóda na výpočet hash
}
}