Meséljen a hashCode és equals metódusok szerződéséről Java-ban.
sobes.tech MI
Válasz az MI-től
A hashCode és equals metódusok Java-ban meghatározzák azok kapcsolatát, és garantálják az objektumok helyes viselkedését a hash-alapú kollekciók használatakor (például HashSet, HashMap).
A szerződés fő szabályai:
- Reflexivitás: Bármely nem null hivatkozási érték
xesetén,x.equals(x)-nektrue-t kell visszaadnia. - Szimmetria: Bármely nem null
xésyhivatkozási érték esetén,x.equals(y)akkor és csak akkortrue, hay.equals(x)istrue. - Tranzitivitás: Bármely nem null
x,yészesetén, hax.equals(y)ésy.equals(z)true, akkorx.equals(z)istrue. - Konzisztencia: Bármely nem null
xésyesetén, azx.equals(y)többszöri hívása ugyanazt az eredményt kell, hogy adja, amennyibenxésynem változnak. - Null nem egyenlőség: Bármely nem null
xesetén,x.equals(null)-nakfalse-t kell visszaadnia.
És a fő szabály, ami összeköti a hashCode-ot és az equals-t:
- Ha két objektum egyenlő az
equals(Object)módszer szerint, akkor ezekhashCode()hívásának eredménye ugyanaz a szám kell, hogy legyen. - Fordítva nem igaz: ha két objektumnak ugyanaz a hash-kódja, az nem jelenti, hogy egyenlőek.
A szerződés értéke:
A szerződés megsértése helytelen működést eredményezhet a kollekciókban. Például, ha két egyenlő objektum különböző hash-kódokat ad vissza, a HashMap külön "kosarakba" helyezheti őket, és nem találhatja meg az egyik objektumot a másik alapján, még akkor sem, ha logikailag egyenlőek.
Példa helyes megvalósításra:
// Példa osztály helyes `equals` és `hashCode`-szal
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; // Bűvös szám, általában prímszám
result = 31 * result + x;
result = 31 * result + y;
return result;
}
// Getter-ek (nem kötelező az `equals`/`hashCode` példához)
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Használat:
- Mindig felülírni mindkét metódust (
equalséshashCode) együtt. - A
hashCodekiszámításakor ugyanazokat a mezőket használja, mint azequals. - Próbáljon "jó" hash függvényeket készíteni, amelyek egyenletesen osztják el a hash-kódokat, minimalizálva az ütközéseket (amikor különböző objektumok ugyanazt a hash-kódot kapják), és javítva a hash-alapú kollekciók teljesítményét.
- Primitívek esetén használja azok értékeit. Objektumok esetén hívja meg a
hashCode()-ot. Tömbök esetén használja azArraysosztály metódusait.
Java 7+ esetén ajánlott az Objects.equals(Object a, Object b) és az Objects.hash(Object... values) használata a kód egyszerűsítése érdekében.
Példa az Objects-szel:
// Osztály példa `equals` és `hashCode`-szal az `Objects` használatával
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; // A összehasonlítás logikája változatlan
}
@Override
public int hashCode() {
return Objects.hash(x, y); // Kényelmes módszer a hash kiszámítására
}
}