Prinsip Hash

Pertama sekali, sebelum kita mentakrifkan kod cincang Java, kita perlu memahami apa itu pencincangan dan untuk apa ia. Hashing ialah proses menggunakan fungsi cincang pada sesetengah data. Fungsi hash hanyalah fungsi matematik. Jangan risau tentang ini! "Matematik" tidak selalu bermaksud "rumit". Di sini hanya bermakna kita mempunyai beberapa data dan peraturan tertentu yang memetakan data ke dalam set aksara (kod). Sebagai contoh, ia boleh menjadi sifir heksadesimal. Kami mempunyai beberapa data dalam sebarang saiz pada input, dan menggunakan fungsi cincang padanya. Pada output, kami mendapat data bersaiz tetap, katakan, 32 aksara. Biasanya, fungsi seperti itu menukar sekeping data yang besar kepada nilai integer yang kecil. Hasil kerja fungsi ini dipanggil kod cincang. Fungsi hash digunakan secara meluas dalam kriptografi, dan beberapa kawasan lain juga. Fungsi hash boleh berbeza,
  • Objek tertentu mempunyai kod cincang tertentu.
  • Jika dua objek adalah sama, kod cincang mereka adalah sama. Sebaliknya tidak benar.
  • Jika kod cincang berbeza, maka objek pasti tidak sama.
  • Objek yang berbeza mungkin mempunyai kod cincang yang sama. Walau bagaimanapun, ia adalah peristiwa yang sangat tidak mungkin. Pada ketika ini, kita mengalami perlanggaran, situasi, di mana kita boleh kehilangan data.
Fungsi cincang "betul" meminimumkan kebarangkalian perlanggaran.

Hashcode dalam Java

Dalam fungsi hash Java biasanya disambungkan kepada kaedah hashCode() . Tepatnya, hasil penggunaan fungsi cincang pada Objek ialah kod cincang. Setiap objek Java mempunyai kod cincang. Secara umum Kod Hash ialah nombor yang dikira oleh kaedah hashCode() kelas Object. Biasanya, pengaturcara mengatasi kaedah ini untuk objek mereka serta berkaitan dengan hashCode() kaedah equals() untuk pemprosesan data tertentu yang lebih cekap. Kaedah hashCode() mengembalikan nilai int (4 bait), yang merupakan perwakilan berangka objek. Kod cincang ini digunakan, contohnya, oleh koleksi untuk penyimpanan data yang lebih cekap dan, oleh itu, akses yang lebih pantas kepada mereka. Secara lalai, hashCode()fungsi untuk objek mengembalikan nombor sel memori tempat objek disimpan. Oleh itu, jika tiada perubahan dibuat pada kod aplikasi, maka fungsi itu harus mengembalikan nilai yang sama. Jika kod berubah sedikit, nilai kod cincang juga berubah. Apakah kod cincang yang digunakan dalam Java? Pertama sekali kod cincang Java membantu program berjalan lebih pantas. Sebagai contoh, jika kita membandingkan dua objek o1dan o2beberapa jenis, operasi o1.equals(o2)mengambil masa kira-kira 20 kali lebih lama daripada o1.hashCode() == o2.hashCode().

Java sama dengan()

Dalam kelas induk Object, bersama-sama dengan kaedah hashCode() , terdapat juga equals() , fungsi yang digunakan untuk menyemak kesamaan dua objek. Pelaksanaan lalai fungsi ini hanya menyemak pautan dua objek untuk kesetaraan mereka. equals() dan hashCode() mempunyai kontrak mereka, jadi jika anda mengatasi salah satu daripadanya, anda harus mengatasi yang lain, agar tidak melanggar kontrak ini.

Melaksanakan kaedah hashCode().

Contoh

Mari buat Watak kelas dengan satu medan — nama . Selepas itu, kami mencipta dua objek kelas Character , character1 , dan character2 dan menetapkannya dengan nama yang sama. Jika kita menggunakan hashCode() dan equals() lalai bagi kelas Object , kita pasti akan mendapat objek yang berbeza, bukan sama. Begitulah cara kod cincang dalam Java berfungsi. Mereka akan mempunyai kod cincang yang berbeza kerana ia berada dalam sel memori yang berbeza dan hasil operasi equals() adalah palsu.

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));
    }
}
Hasil daripada menjalankan program:

Arnold
1595428806
Arnold
1072408673
false
Dua nombor 10 digit dalam konsol ialah kod cincang. Bagaimana jika kita ingin mempunyai objek yang sama jika mereka mempunyai nama yang sama? Apa yang patut kita buat? Jawapannya: kita harus mengatasi kaedah hashCode() dan equals() kelas Objek untuk kelas Aksara kita . Kami boleh melakukannya secara automatik dalam IDEA IDE, hanya tekan alt + insert pada papan kekunci anda dan pilih Generate -> equals() dan hashCode() . Apakah Java hashCode() - 2Dalam kes contoh kami, kami mempunyai kod seterusnya:

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));
    }
}
Hasil daripada menjalankan kod ini:

Arnold
1969563338
Arnold
1969563338
true
Jadi sekarang program ini mengenal pasti objek kita sebagai sama dan mereka mempunyai kod cincang yang sama.

Contoh kod cincang Java:

Kod hash anda sendiri() dan sama()

Anda juga boleh mencipta realisasi equals() dan hashCode() anda sendiri , tetapi berhati-hati dan ingat untuk meminimumkan perlanggaran kod cincang. Berikut ialah contoh kaedah hashCode() dan equals() kami sendiri dalam kelas Pelajar :

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));
   }
}
Dan kelas Utama untuk menunjukkan kerja mereka:

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

Apakah kod cincang digunakan?

Pertama sekali, kod cincang membantu program berjalan lebih pantas. Sebagai contoh, jika kita membandingkan dua objek o1dan o2beberapa jenis, operasi o1.equals(o2)mengambil masa kira-kira 20 kali lebih banyak daripada o1.hashCode() == o2.hashCode(). Dalam Java prinsip pencincangan berdiri di belakang beberapa koleksi popular, seperti HashMap , HashSet dan HashTable .

Kesimpulan

Setiap objek Java mempunyai kaedah hashCode() dan equals() yang diwarisi daripada kelas Object . Untuk mendapatkan mekanisme kesamaan kerja yang baik, anda lebih baik mengatasi kaedah hashcode() dan equals() untuk kelas anda sendiri. Menggunakan kod cincang menjadikan program berjalan lebih pantas.