CodeGym /Java Blog /Willekeurig /Java-hashCode()
John Squirrels
Niveau 41
San Francisco

Java-hashCode()

Gepubliceerd in de groep Willekeurig

Hash-principe

Allereerst moeten we, voordat we de Java-hashcode definiëren, begrijpen wat hashing is en waar het voor dient. Hashing is het toepassen van een hashfunctie op bepaalde gegevens. Een hash-functie is slechts een wiskundige functie. Maak je hier geen zorgen over! "Wiskundig" betekent niet altijd "ingewikkeld". Hier betekent het alleen dat we wat gegevens hebben en een bepaalde regel die de gegevens in een reeks tekens (code) in kaart brengt. Het kan bijvoorbeeld een hexadecimaal cijfer zijn. We hebben wat gegevens van elke grootte bij de invoer en passen er een hash-functie op toe. Aan de uitvoer krijgen we gegevens van een vaste grootte, bijvoorbeeld 32 tekens. Gewoonlijk zet zo'n functie een groot stuk gegevens om in een kleine integerwaarde. Het resultaat van dit functiewerk wordt een hashcode genoemd. Hash-functies worden veel gebruikt in cryptografie, en ook op sommige andere gebieden. Hash-functies kunnen verschillend zijn,
  • Een bepaald object heeft een bepaalde hashcode.
  • Als twee objecten gelijk zijn, zijn hun hashcodes hetzelfde. Het omgekeerde is niet waar.
  • Als de hashcodes verschillend zijn, zijn de objecten zeker niet gelijk.
  • Verschillende objecten kunnen dezelfde hashcode hebben. Het is echter een zeer onwaarschijnlijke gebeurtenis. Op dit punt hebben we een botsing, een situatie waarin we gegevens kunnen verliezen.
De "juiste" hash-functie minimaliseert de kans op botsingen.

Hashcode in Java

In Java is de hashfunctie meestal verbonden met de methode hashCode() . Precies, het resultaat van het toepassen van een hashfunctie op een object is een hashcode. Elk Java-object heeft een hashcode. Over het algemeen is de hashcode een getal dat wordt berekend door de methode hashCode()Object van de klasse. Gewoonlijk negeren programmeurs deze methode voor hun objecten, evenals de methode equals() gerelateerd aan hashCode( ) voor een efficiëntere verwerking van specifieke gegevens. De methode hashCode() retourneert een int-waarde (4 bytes), wat een numerieke weergave is van het object. Deze hashcode wordt bijvoorbeeld door collecties gebruikt voor efficiëntere opslag van gegevens en daardoor snellere toegang hiertoe. Standaard is de hashCode()functie voor een object retourneert het nummer van de geheugencel waarin het object is opgeslagen. Als er dus geen wijzigingen worden aangebracht in de toepassingscode, moet de functie dezelfde waarde retourneren. Als de code iets verandert, verandert ook de waarde van de hashcode. Waar wordt de hashcode voor gebruikt in Java? Allereerst helpen Java-hashcodes om programma's sneller te laten werken. Als we bijvoorbeeld twee objecten o1en o2van een bepaald type vergelijken, o1.equals(o2)kost de bewerking ongeveer 20 keer meer tijd dan o1.hashCode() == o2.hashCode().

Java is gelijk aan()

In de bovenliggende klasse is er Objectnaast de methode hashCode() ook equals() , de functie die wordt gebruikt om de gelijkheid van twee objecten te controleren. De standaardimplementatie van deze functie controleert eenvoudigweg de koppelingen van twee objecten op hun gelijkwaardigheid. equals() en hashCode() hebben hun contract, dus als u een van hen overschrijft, moet u de andere overschrijven om dit contract niet te verbreken.

De methode hashCode() implementeren

Voorbeeld

Laten we een klasse Karakter maken met één veld - naam . Daarna maken we twee objecten van de klasse Character , character1 en character2 en stellen ze dezelfde naam in. Als we de standaard hashCode() en equals() van de klasse Object gebruiken , krijgen we zeker verschillende, niet gelijke objecten. Zo werkt hashcode in Java. Ze hebben verschillende hashcodes omdat ze zich in verschillende geheugencellen bevinden en het resultaat van de bewerking equals() is onwaar.

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));
    }
}
Het resultaat van het uitvoeren van het programma:

Arnold
1595428806
Arnold
1072408673
false
Twee 10-cijferige nummers in de console zijn hashcodes. Wat als we gelijke objecten willen hebben als ze dezelfde namen hebben? Wat moeten we doen? Het antwoord: we moeten de methoden hashCode() en equals() van de klasse Object overschrijven voor onze klasse Character . We zouden het automatisch kunnen doen in IDEA IDE, druk gewoon op alt + insert op je toetsenbord en kies Generate -> equals() en hashCode() . Wat is Java-hashCode() - 2In het geval van ons voorbeeld hebben we de volgende code:

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));
    }
}
Het resultaat van het uitvoeren van deze code:

Arnold
1969563338
Arnold
1969563338
true
Dus nu identificeert het programma onze objecten als gelijk en hebben ze dezelfde hashcodes.

Voorbeeld van Java-hashcode:

Je eigen hashCode() en is gelijk aan()

U kunt ook uw eigen realisaties van equals() en hashCode() maken , maar wees voorzichtig en vergeet niet de hashcode-botsingen te minimaliseren. Hier is een voorbeeld van onze eigen methoden hashCode() en equals() in de klasse 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));
   }
}
En de Hoofdklasse om hun werk te demonstreren:

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));
   }
}

Waar wordt de hashcode voor gebruikt?

Allereerst helpen hashcodes om programma's sneller te laten werken. Als we bijvoorbeeld twee objecten van een bepaald type vergelijken o1, o2kost de bewerking o1.equals(o2)ongeveer 20 keer meer tijd dan o1.hashCode() == o2.hashCode(). In Java staat het hashing-principe achter enkele populaire collecties, zoals HashMap , HashSet en HashTable .

Conclusie

Elk Java-object heeft de methoden hashCode() en equals() die zijn geërfd van de klasse Object . Om een ​​goed werkend gelijkheidsmechanisme te krijgen, kun je beter de methoden hashcode() en equals() overschrijven voor je eigen klassen. Door hashcodes te gebruiken, werken programma's sneller.
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION