Hash İlkesi
Öncelikle Java hashcode'u tanımlamadan önce hash nedir ve ne işe yarar onu anlamamız gerekir. Hashing, bazı verilere bir hash işlevi uygulama işlemidir. Hash fonksiyonu sadece matematiksel bir fonksiyondur. Bunun için endişelenme! "Matematiksel" her zaman "karmaşık" anlamına gelmez. Burada sadece bazı verilere ve verileri bir dizi karaktere (kod) eşleyen belirli bir kurala sahip olduğumuz anlamına gelir. Örneğin, onaltılık bir şifre olabilir. Girdide herhangi bir boyutta bazı verilerimiz var ve bunlara bir hash işlevi uyguluyoruz. Çıktıda, örneğin 32 karakter gibi sabit boyutlu bir veri alıyoruz. Genellikle, bu tür bir işlev, büyük bir veri parçasını küçük bir tamsayı değerine dönüştürür. Bu işlev çalışmasının sonucu bir hash kodu olarak adlandırılır. Karma işlevler, kriptografide ve diğer bazı alanlarda da yaygın olarak kullanılmaktadır. Hash fonksiyonları farklı olabilir,
- Belirli bir nesnenin belirli bir karma kodu vardır.
- İki nesne eşitse, hash kodları da aynıdır. Tersi doğru değil.
- Hash kodları farklıysa, nesneler kesinlikle eşit değildir.
- Farklı nesneler aynı hash koduna sahip olabilir. Ancak bu pek olası olmayan bir olaydır. Bu noktada bir çakışma, veri kaybedebileceğimiz bir durum var.
"Uygun" hash işlevi, çarpışma olasılığını en aza indirir.
Java'da hash kodu
Java'da hash işlevi genellikle
hashCode() yöntemine bağlıdır . Kesin olarak, bir Nesneye bir karma işlevi uygulamanın sonucu bir karma kodudur. Her Java nesnesinin bir karma kodu vardır. Genel olarak Hash Kodu, sınıfın
hashCode() yöntemi tarafından hesaplanan bir sayıdır
Object
. Genellikle, programcılar bu yöntemi nesnelerinin yanı sıra belirli verilerin daha verimli işlenmesi için
hashCode() ile ilgili equals
() yöntemini geçersiz kılar. hashCode
() yöntemi, nesnenin sayısal bir temsili olan bir int (4 bayt) değeri döndürür. Bu hashcode, örneğin koleksiyonlar tarafından verilerin daha verimli depolanması ve dolayısıyla bunlara daha hızlı erişim için kullanılır. Varsayılan olarak,
hashCode()bir nesne için işlev, nesnenin depolandığı bellek hücresinin numarasını döndürür. Bu nedenle, uygulama kodunda herhangi bir değişiklik yapılmadıysa, işlev aynı değeri döndürmelidir. Kod biraz değişirse, hashcode değeri de değişir. Java'da kullanılan karma kod nedir? Her şeyden önce, Java karma kodları programların daha hızlı çalışmasına yardımcı olur.
o1
Örneğin, iki nesneyi ve herhangi bir türü karşılaştırırsak
o2
, işlem
o1.equals(o2)
yaklaşık 20 kat daha fazla zaman alır
o1.hashCode() == o2.hashCode()
.
Java eşittir ()
Üst sınıfta ,
hashCode()Object
yönteminin yanı sıra , iki nesnenin eşitliğini kontrol etmek için kullanılan
equals() işlevi de vardır . Bu işlevin varsayılan uygulaması, iki nesnenin bağlantılarını eşdeğerlik açısından kontrol eder.
equals() ve
hashCode()' un kendi sözleşmeleri vardır, dolayısıyla birini geçersiz kılarsanız, bu sözleşmeyi bozmamak için diğerini geçersiz kılmalısınız.
hashCode() yöntemini uygulama
Örnek
Tek bir alana sahip bir Karakter sınıfı oluşturalım -
name .
Bundan sonra, Karakter sınıfından,
karakter1 ve
karakter2 olmak üzere iki nesne yaratıyoruz ve onlara aynı adı veriyoruz.
Object sınıfının varsayılan
hashCode() ve
equals() öğelerini kullanırsak , eşit değil, kesinlikle farklı nesneler elde ederiz. Java'da hashcode böyle çalışır. Farklı bellek hücrelerinde oldukları için farklı hash kodlarına sahip olacaklar ve
equals() işleminin sonucu yanlış olacaktır.
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));
}
}
Programı çalıştırmanın sonucu:
Arnold
1595428806
Arnold
1072408673
false
Konsoldaki iki adet 10 haneli sayı karma kodlardır. Aynı ada sahiplerse eşit nesnelere sahip olmak istersek ne olur? Ne yapmalıyız?
Cevap: Karakter sınıfımız için
Object sınıfının hashCode() ve
equals() yöntemlerini geçersiz kılmalıyız . Bunu IDEA IDE'de otomatik olarak yapabiliriz, sadece klavyenizde
alt + insert tuşlarına basın ve Generate -> equals() ve hashCode() öğelerini seçin . Örneğimizde, bir sonraki kodumuz var:
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));
}
}
Bu kodu çalıştırmanın sonucu:
Arnold
1969563338
Arnold
1969563338
true
Böylece program, nesnelerimizi eşit olarak tanımlar ve aynı karma kodlara sahiptirler.
Java karma kodu örneği:
Kendi hashCode() ve eşittir()
Kendi equals() ve
hashCode() gerçekleştirmelerinizi de oluşturabilirsiniz , ancak dikkatli olun ve karma kod çarpışmalarını en aza indirmeyi unutmayın. İşte
Student sınıfındaki kendi
hashCode() ve
equals() yöntemlerimize bir örnek :
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));
}
}
Ve çalışmalarını göstermek için
Ana sınıf:
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));
}
}
Hashcode ne için kullanılır?
Her şeyden önce, karma kodlar programların daha hızlı çalışmasına yardımcı olur.
o1
Örneğin, iki nesneyi ve bir türü karşılaştırırsak
o2
, işlem
o1.equals(o2)
o1.hashCode() == o2.hashCode() işleminden yaklaşık 20 kat daha fazla zaman alır.
Java'da karma ilkesi, HashMap ,
HashSet ve
HashTable gibi bazı popüler koleksiyonların arkasında durur .
Çözüm
Her Java nesnesi,
Object sınıfından miras alınan hashCode() ve
equals() yöntemlerine sahiptir . İyi çalışan bir eşitlik mekanizması elde etmek için kendi sınıflarınız için
hashcode() ve
equals() yöntemlerini geçersiz kılmanız daha iyi olur . Karma kodları kullanmak, programların daha hızlı çalışmasını sağlar.
GO TO FULL VERSION