Hash-elv
Először is, mielőtt meghatároznánk a Java hashkódot, meg kell értenünk, hogy mi a hash, és mire való. A kivonatolás olyan folyamat, amelynek során egyes adatokra hash függvényt alkalmaznak. A hash függvény csak egy matematikai függvény. Ne törődj ezzel! A „matematikai” nem mindig azt jelenti, hogy „bonyolult”. Itt ez csak azt jelenti, hogy van néhány adatunk és egy bizonyos szabályunk, amely leképezi az adatokat egy karakterkészletre (kódra). Ez lehet például egy hexadecimális titkosítás. Bármilyen méretű adatunk van a bemeneten, és alkalmazunk rá egy hash függvényt. A kimeneten egy fix méretű adatot kapunk, mondjuk 32 karaktert. Általában ez a fajta függvény egy nagy adatot kis egész számmá alakít át. Ennek a függvénymunkának az eredményét hash kódnak nevezzük. A hash függvényeket széles körben használják a kriptográfiában és néhány más területen is. A hash függvények különbözőek lehetnek,
- Egy adott objektumnak van egy adott hashkódja.
- Ha két objektum egyenlő, akkor a hashkódjuk megegyezik. Ennek a fordítottja nem igaz.
- Ha a hash kódok különböznek, akkor az objektumok biztosan nem azonosak.
- A különböző objektumok ugyanazzal a hash kóddal rendelkezhetnek. Ez azonban nagyon valószínűtlen esemény. Ezen a ponton van egy ütközés, egy olyan helyzet, amikor adatokat veszíthetünk.
A „megfelelő” hash függvény minimalizálja az ütközések valószínűségét.
Hashcode Java nyelven
Java-ban a hash függvény általában a hashCode() metódushoz kapcsolódik . Pontosabban, ha egy hash függvényt alkalmazunk egy objektumra, akkor ez egy hashkód. Minden Java objektumnak van hash kódja. Általában a Hash Code egy szám, amelyet az osztály
hashCode() metódusa számít ki
Object
. Általában a programozók felülírják ezt a metódust az objektumaiknál, valamint a
hashCode() -hoz kapcsolják az
equals() metódust az adott adatok hatékonyabb feldolgozása érdekében. A
hashCode() metódus egy int (4 bájt) értéket ad vissza, amely az objektum numerikus ábrázolása. Ezt a hashkódot például a gyűjtemények használják az adatok hatékonyabb tárolására, és ennek megfelelően a gyorsabb hozzáférésre. Alapértelmezés szerint a
hashCode()Az objektum függvénye annak a memóriacellának a számát adja vissza, ahol az objektum tárolva van. Ezért, ha nem történik változás az alkalmazás kódjában, akkor a függvénynek ugyanazt az értéket kell visszaadnia. Ha a kód kissé megváltozik, a hashcode értéke is megváltozik. Mire használható a hashkód a Java-ban? Mindenekelőtt a Java hashkódok segítenek a programok gyorsabb futtatásában. Például, ha összehasonlítunk két objektumot
o1
és
o2
valamilyen típusú, a művelet
o1.equals(o2)
körülbelül 20-szor több időt vesz igénybe, mint
o1.hashCode() == o2.hashCode()
.
Java egyenlő ()
A szülőosztályban a
hashCode()Object
metódus mellett megtalálható
az equals() függvény is, amely két objektum egyenlőségének ellenőrzésére szolgál. Ennek a függvénynek az alapértelmezett megvalósítása egyszerűen ellenőrzi két objektum hivatkozásait az egyenértékűség szempontjából.
az equals() és
a hashCode()-nak megvan a szerződése, tehát ha felülírja az egyiket, felül kell írnia a másikat is, hogy ne szegje meg ezt a szerződést.
A hashCode() metódus megvalósítása
Példa
Hozzunk létre egy osztályt
Karakter egy mezővel —
név . Ezután létrehozunk két
karakterosztályú objektumot ,
a karakter1 és
a karakter2 , és ugyanazt a nevet adjuk nekik. Ha az
Object osztály alapértelmezett hashCode()- ját és
equals()-jét használjuk , akkor biztosan különböző, nem egyenlő objektumokat kapunk. Így működik a hashcode a Java-ban. Különböző hashkódjaik lesznek, mert különböző memóriacellákban vannak, és az
equals() művelet eredménye hamis lesz.
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));
}
}
A program futtatásának eredménye:
Arnold
1595428806
Arnold
1072408673
false
A konzolban található két 10 jegyű szám hashkód. Mi van akkor, ha egyenlő objektumokat akarunk, ha azonos nevük van? Mit tehetünk? A válasz: felül kell bírálnunk az
Object osztály hashCode() és
equals() metódusait
a Character osztályunkban . Az IDEA IDE-ben automatikusan megtehetjük, csak nyomja meg
az Alt + Enter billentyűt a billentyűzeten, és válassza
a Generate -> equals() és a hashCode() lehetőséget . Példánk esetében a következő kódot kapjuk:
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));
}
}
A kód futtatásának eredménye:
Arnold
1969563338
Arnold
1969563338
true
Tehát most a program egyenlőnek azonosítja az objektumainkat, és azonos hashkódokkal rendelkeznek.
Java hashcode példa:
Saját hashCode() and equals()
Létrehozhat saját
equals() és
hashCode() megvalósításokat is, de legyen óvatos, és ne felejtse el minimalizálni a hashcode ütközéseket. Íme egy példa a saját
hashCode() és
equals() metódusainkra a
Student osztályban:
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));
}
}
A főosztály pedig bemutatja munkájukat:
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));
}
}
Mire használható a hashcode?
Mindenekelőtt a hashkódok segítenek a programok gyorsabb futtatásában. Például, ha összehasonlítunk két objektumot
o1
és
o2
valamilyen típusú, a művelet
o1.equals(o2)
körülbelül 20-szor több időt vesz igénybe, mint az o1.hashCode() == o2.hashCode(). A Java hashelési elve néhány népszerű gyűjtemény mögött áll, mint például
a HashMap ,
HashSet és
HashTable .
Következtetés
Minden Java objektum rendelkezik
az Object osztályból örökölt
hashCode() és
equals() metódusokkal . Egy jól működő egyenlőségi mechanizmus eléréséhez jobb, ha felülírja
a hashcode() és
equals() metódusokat a saját osztályaiban. A hashkódok használatával gyorsabban futnak a programok.
GO TO FULL VERSION