Sobes.tech
Middle

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:

  1. Kui kaks objekti on equals järgi võrdsed, peavad nende hashCode-d olema samad.
  2. Kui kaks objekti ei ole equals järgi võrdsed, võivad nende hashCode-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 equals jä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:

  1. Objects.hash() kasutamine (alates Java 7): kõige lihtsam ja soovitatav viis. See on null-turvaline ja kasutab antud väljade hashCode-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
        }
    }
    
  2. 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).

  1. IDE kasutamine: Enamik kaasaegseid IDE-sid (nt IntelliJ IDEA, Eclipse) võimaldab automaatselt genereerida equals() ja hashCode() 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.