Miks ja kuidas üle kirjutada meetod hashCode?
sobes.tech AI
Vastus AI-lt
hashCode meetodit kasutatakse objekti täisarvse hash-koodi saamiseks. See on vajalik HashMap, HashSet ja HashTable kogumite õige toimimise jaoks. Kui objekti lisatakse sellesse kogumisse, kasutatakse selle hash-koodi, et määrata "ämber" (bucket), kuhu objekt paigutatakse. Objekti otsimisel arvutatakse hash-kood uuesti, et kiiresti määrata, millist ämbrikest kontrollida.
hashCode ülekirjutamine on vajalik, kui olete equals meetodi üle kirjutanud. equals ja hashCode vahelise lepingu kohaselt:
- Kui kaks objekti on
equalsjärgi võrdsed, peavad nendehashCode-d olema samad. - Kui kaks objekti ei ole
equalsjärgi võrdsed, võivad nendehashCode-d olla erinevad, kuid parem on, kui need on erinevad, et parandada kogumite jõudlust.
Kui te equals meetodi üle kirjutate ilma hashCode üle kirjutamata, võivad võrdsed objektid saada erinevad hashCode-d (välja arvatud juhuslikud kokkulangemised), mis põhjustab kogumite ebaõiget tööd:
- Objekti, mida peetakse
equalsjärgi võrdseks, paigutatakse erinevatesse ämbrikestesse. - Võrdse objekti otsing võib ebaõnnestuda, kuna kontrollitakse ainult ühte ämbrikest, mis on määratud
hashCode-ga.
hashCode-i ülekirjutamiseks kasutatakse tavaliselt objekti equals-is osalevate väljade hashCode-d kombinatsioonina.
Kõige levinumad meetodid:
-
Objects.hash()kasutamine (alates Java 7): kõige lihtsam ja soovitatav viis. See on null-turvaline ja kasutab antud väljadehashCode-d.// Näide `Objects.hash()` kasutamisest import java.util.Objects; public class MyClass { private int field1; private String field2; // ... konstruktor, getterid, setterid @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MyClass myClass = (MyClass) o; return field1 == myClass.field1 && Objects.equals(field2, myClass.field2); } @Override public int hashCode() { return Objects.hash(field1, field2); // väljastab `equals`-is osalevad väljad } } -
Käsitsi (lihtsa algoritmi kasutamine): madalama taseme lähenemine, mis võib olla kasulik mõistmiseks, kuid on suurem vigu tekitav. Tavaliselt kasutatakse lihtsat korrutamist ja liitmist.
// Näide käsitsi `hashCode` ülekirjutamisest public class MyClass { private int field1; private String field2; // ... konstruktor, getterid, setterid @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MyClass myClass = (MyClass) o; return field1 == myClass.field1 && Objects.equals(field2, myClass.field2); } @Override public int hashCode() { int result = 17; // algusväärtus (ükskõik mis paaritu arv) result = 31 * result + field1; // korrutame 31-ga ja lisame välja hash-koodi result = 31 * result + (field2 != null ? field2.hashCode() : 0); // null-ide käsitlemine return result; } }
Kasutades 31 arvuna, kuna see võib olla efektiivselt optimeeritud kompilaatoriga (31 * i == (i << 5) - i).
- IDE kasutamine: Enamik kaasaegseid IDE-sid (nt IntelliJ IDEA, Eclipse) võimaldab automaatselt genereerida
equals()jahashCode()meetodid. See on kõige turvalisem ja soovitatav lähenemine, kuna nad genereerivad koodi vastavalt parimatele praktikatele.
hashCode-i üle kirjutamise peamine eesmärk on tagada, et võrdsed objektid omavad samu hash-koodid, mis on kriitilise tähtsusega hash-põhiste kogumite korrektseks toimimiseks.