CodeGym /Blog Java /Aleatoriu /Java hashCode()
John Squirrels
Nivel
San Francisco

Java hashCode()

Publicat în grup

Principiul Hash

În primul rând, înainte de a defini codul hash Java, trebuie să înțelegem ce este hashing și pentru ce este acesta. Hashing este un proces de aplicare a unei funcții hash unor date. O funcție hash este doar o funcție matematică. Nu vă faceți griji pentru asta! „Matematic” nu înseamnă întotdeauna „complicat”. Aici înseamnă doar că avem niște date și o anumită regulă care mapează datele într-un set de caractere (cod). De exemplu, ar putea fi un cifru hexazecimal. Avem câteva date de orice dimensiune la intrare și le aplicăm o funcție hash. La ieșire, obținem date de dimensiune fixă, să zicem, 32 de caractere. De obicei, acest tip de funcție convertește o bucată mare de date într-o valoare întreagă mică. Rezultatul acestei funcții se numește cod hash. Funcțiile hash sunt utilizate pe scară largă în criptografie și în alte domenii. Funcțiile hash pot fi diferite,
  • Un anumit obiect are un anumit hashcode.
  • Dacă două obiecte sunt egale, codurile lor hash sunt aceleași. Reversul nu este adevărat.
  • Dacă codurile hash sunt diferite, atunci obiectele nu sunt egale cu siguranță.
  • Diferite obiecte pot avea același cod hash. Cu toate acestea, este un eveniment foarte puțin probabil. În acest moment, avem o coliziune, o situație în care putem pierde date.
Funcția hash „corectă” minimizează probabilitatea de coliziuni.

Hashcode în Java

În Java, funcția hash este de obicei conectată la metoda hashCode() . Mai exact, rezultatul aplicării unei funcții hash unui Obiect este un hashcode. Fiecare obiect Java are un cod hash. În general, Hash Code este un număr calculat prin metoda hashCode() a Objectclasei. De obicei, programatorii înlocuiesc această metodă pentru obiectele lor, precum și în legătură cu metoda hashCode() equals () pentru o procesare mai eficientă a anumitor date. Metoda hashCode() returnează o valoare int (4 octeți), care este o reprezentare numerică a obiectului. Acest cod hash este folosit, de exemplu, de colecții pentru o stocare mai eficientă a datelor și, în consecință, un acces mai rapid la acestea. În mod implicit, hashCode()funcția pentru un obiect returnează numărul celulei de memorie în care este stocat obiectul. Prin urmare, dacă nu se fac modificări la codul aplicației, atunci funcția ar trebui să returneze aceeași valoare. Dacă codul se modifică ușor, se schimbă și valoarea hashcode. Pentru ce este folosit codul hash în Java? În primul rând, codurile hash Java ajută programele să ruleze mai repede. De exemplu, dacă comparăm două obiecte o1și o2de un anumit tip, operația o1.equals(o2)durează de aproximativ 20 de ori mai mult decât o1.hashCode() == o2.hashCode().

Java este egal()

În clasa părinte Object, alături de metoda hashCode() există și equals() , funcția care este folosită pentru a verifica egalitatea a două obiecte. Implementarea implicită a acestei funcții verifică pur și simplu legăturile a două obiecte pentru echivalența lor. equals() și hashCode() au contractul lor, așa că dacă îl suprascrieți pe unul dintre ele, ar trebui să îl înlocuiți pe celălalt, pentru a nu rupe acest contract.

Implementarea metodei hashCode().

Exemplu

Să creăm o clasă Caracter cu un câmp — nume . După aceea, creăm două obiecte din clasa Character , caracterul1 și caracterul2 și le setăm același nume. Dacă folosim hashCode() și equals() implicit ale clasei Object , cu siguranță vom obține obiecte diferite, nu egale. Așa funcționează hashcode în Java. Vor avea coduri hash diferite, deoarece sunt în celule de memorie diferite, iar rezultatul operației equals() va fi fals.

import java.util.Objects;

public class Character {
    private String Name;

    public Character(String name) {
        Name = name;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    } 

    public static void main(String[] args) {
        Character character1 = new Character("Arnold");
        System.out.println(character1.getName());
        System.out.println(character1.hashCode());
        Character character2 = new Character("Arnold");
        System.out.println(character2.getName());
        System.out.println(character2.hashCode());
        System.out.println(character2.equals(character1));
    }
}
Rezultatul rulării programului:

Arnold
1595428806
Arnold
1072408673
false
Două numere de 10 cifre din consolă sunt coduri hash. Ce se întâmplă dacă vrem să avem obiecte egale dacă au aceleași nume? Ce ar trebui sa facem? Răspunsul: ar trebui să suprascriem metodele hashCode() și equals() ale clasei Object pentru clasa noastră Character . Am putea să o facem automat în IDEA IDE, doar apăsați alt + inserare pe tastatură și alegeți Generare -> equals() și hashCode() . Ce este Java hashCode() - 2În cazul exemplului nostru, avem următorul cod:

import java.util.Objects;

public class Character {
    private String Name;

    public Character(String name) {
        Name = name;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Character)) return false;

        Character character = (Character) o;

        return getName() != null ? getName().equals(character.getName()) : character.getName() == null;
    }

    @Override
    public int hashCode() {
        return getName() != null ? getName().hashCode() : 0;
    }

    public static void main(String[] args) {
        Character character1 = new Character("Arnold");
        System.out.println(character1.getName());
        System.out.println(character1.hashCode());
        Character character2 = new Character("Arnold");
        System.out.println(character2.getName());
        System.out.println(character2.hashCode());
        System.out.println(character2.equals(character1));
    }
}
Rezultatul rulării acestui cod:

Arnold
1969563338
Arnold
1969563338
true
Deci acum programul identifică obiectele noastre ca fiind egale și au aceleași coduri hash.

Exemplu de hashcode Java:

Propriul tău hashCode() și equals()

De asemenea, puteți crea propriile realizări equals() și hashCode() , dar aveți grijă și amintiți-vă să minimizați coliziunile hashcode. Iată un exemplu de propriile noastre metode hashCode() și equals() în clasa Student :

import java.util.Date;

public class Student {
   String surname;
   String name;
   String secondName;
   Long birthday; // Long instead of long is used by Gson/Jackson json parsers and various orm databases

   public Student(String surname, String name, String secondName, Date birthday ){
       this.surname = surname;
       this.name = name;
       this.secondName = secondName;
       this.birthday = birthday == null ? 0 : birthday.getTime();
   }
//Java hashcode example
   @Override
   public int hashCode(){
       //TODO: check for nulls
       //return surname.hashCode() ^ name.hashCode() ^ secondName.hashCode() ^ (birthday.hashCode());
       return (surname + name + secondName + birthday).hashCode();
   }
   @Override
   public boolean equals(Object other_) {
       Student other = (Student)other_;
       return (surname == null || surname.equals(other.surname) )
               && (name == null || name.equals(other.name))
               && (secondName == null || secondName.equals(other.secondName))
               && (birthday == null || birthday.equals(other.birthday));
   }
}
Și clasa principală pentru a-și demonstra munca:

import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;

public class Main {
   static HashMap<Student, Integer> cache = new HashMap<Student, Integer>(); // <person, targetPriority>

   public static void main(String[] args) {
       Student sarah1 = new Student("Sarah","Connor", "Jane", null);
       Student sarah2 = new Student("Sarah","Connor", "Jane", new Date(1970, 01-1, 01));
       Student sarah3 = new Student("Sarah","Connor", "Jane", new Date(1959, 02-1, 28)); // date not exists
       Student john = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
       Student johnny = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
       System.out.println(john.hashCode());
       System.out.println(johnny.hashCode());
       System.out.println(sarah1.hashCode());
       System.out.println();
       cache.put(sarah1, 1);
       cache.put(sarah2, 2);
       cache.put(sarah3, 3);
       System.out.println(new Date(sarah1.birthday));
       System.out.println();
       cache.put(john, 5);
       System.out.println(cache.get(john));
       System.out.println(cache.get(johnny));
       cache.put(johnny, 7);
       System.out.println(cache.get(john));
       System.out.println(cache.get(johnny));
   }
}

Pentru ce este folosit codul hash?

În primul rând, codurile hash ajută programele să ruleze mai repede. De exemplu, dacă comparăm două obiecte o1și o2de un anumit tip, operația o1.equals(o2)durează de aproximativ 20 de ori mai mult decât o1.hashCode() == o2.hashCode(). În Java, principiul hashing stă în spatele unor colecții populare, cum ar fi HashMap , HashSet și HashTable .

Concluzie

Fiecare obiect Java are metodele hashCode() și equals() moștenite de la clasa Object . Pentru a obține un mecanism de egalitate bun, ar fi mai bine să suprascrieți metodele hashcode() și equals() pentru propriile clase. Utilizarea codurilor hash face ca programele să ruleze mai rapid.
Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION