Tentang HashCode, di Wikipedia:
Dalam bahasa pemrograman Java, setiap kelas secara implisit atau eksplisit menyediakan metode hashcode (), yang mencerna data yang disimpan dalam contoh kelas menjadi nilai hash tunggal (integer yang ditandatangani 32-bit).
HashCode mengekstrak bilangan bulat 32-bit berdasarkan semua data yang disimpan dalam contoh objek. Tujuan bilangan bulat ini adalah untuk menunjukkan keunikan instance. Ini agak mirip dengan kode MD5, dan setiap file dapat menghasilkan kode MD5 yang unik melalui algoritma MD5. Namun, kode hash di Java tidak benar -benar mengimplementasikan kode hash untuk menghasilkan kode hash yang unik untuk setiap objek, dan masih ada kemungkinan duplikasi tertentu.
Mari kita lihat kelas objek terlebih dahulu. Kita tahu bahwa kelas objek adalah kelas induk langsung atau tidak langsung dari semua kelas dalam program Java dan berada di titik tertinggi dari tingkat kelas. Banyak metode umum didefinisikan dalam kelas objek, termasuk metode kode hashcode yang ingin kita bicarakan, sebagai berikut
Kelas Asli Akhir Publik <?> GetClass (); hashcode int asli int (); public boolean sama (objek obj) {return (this == obj); } public string toString () {return getClass (). getName () + "@" + integer.tohexstring (hashcode ()); }Perhatikan bahwa ada pengubah asli di depan metode kode hash, yang berarti bahwa metode kode hash diterapkan dalam bahasa non-java. Metode spesifik diimplementasikan secara eksternal dan mengembalikan alamat objek memori.
Di banyak kelas Java, sama dengan dan metode kode hashcode ditulis ulang. Mengapa ini? Kelas string yang paling umum, seperti jika saya mendefinisikan dua string dengan karakter yang sama, maka ketika membandingkannya, hasil yang saya inginkan harus sama. Jika Anda tidak mengganti metode kode yang setara dan hash, mereka pasti tidak akan sama, karena alamat memori dari kedua objek berbeda.
public int hashCode () {int h = hash; if (h == 0) {int off = offset; char val [] = nilai; int len = hitung; untuk (int i = 0; i <len; i ++) {h = 31*h+val [OFF ++]; } hash = h; } return h; }Faktanya, kode ini adalah implementasi dari ekspresi matematika ini
S [0]*31^(n-1) + S [1]*31^(n-2) + ... + S [n-1]
S [i] adalah karakter i-th dari string, dan n adalah panjang string. Lalu mengapa menggunakan 31 di sini, bukan nomor lain? Java yang efektif mengatakan ini: Alasan mengapa 31 dipilih adalah karena itu adalah bilangan prima yang aneh. Jika pengganda adalah angka genap dan perkalian meluap, informasi akan hilang, karena mengalikan dengan 2 setara dengan operasi shift. Manfaat menggunakan bilangan prima tidak jelas, tetapi hasil hash secara konvensional digunakan untuk menghitung hasil hash. 31 memiliki fitur yang baik, yaitu menggunakan shift dan pengurangan alih-alih multiplikasi untuk mendapatkan kinerja yang lebih baik: 31*i == (i << 5) -i. VM dapat secara otomatis menyelesaikan optimasi ini.
Seperti yang Anda lihat, kelas string menggunakan nilai nilainya sebagai parameter untuk menghitung kode hash, yaitu, nilai yang sama pasti akan memiliki nilai kode hash yang sama. Ini juga mudah dimengerti, karena nilai nilainya sama, jadi jika sama dengan perbandingan juga sama, metode yang sama sama, maka kode hash harus sama. Sebaliknya tidak selalu benar. Itu tidak menjamin bahwa kode hash yang sama harus memiliki objek yang sama.
Fungsi hash yang bagus harus terlihat seperti ini: menghasilkan kode hash yang tidak setara untuk objek yang berbeda.
Dalam kasus ideal, fungsi hash harus secara merata mendistribusikan contoh yang tidak sama dalam set ke semua kode hash yang mungkin. Sangat sulit untuk mencapai situasi ideal ini, setidaknya Java belum mencapainya. Karena kita dapat melihat bahwa kode hash dihasilkan non-acak, dan memiliki aturan tertentu, yang merupakan persamaan matematika di atas. Kita dapat membangun beberapa yang memiliki kode hash yang sama tetapi nilai nilai yang berbeda, misalnya: kode hash AA dan BB adalah sama.
Kode berikut:
kelas publik utama {public static void main (string [] args) {main m = new main (); System.out.println (m); System.out.println (integer.tohexstring (m.hashcode ())); String a = "aa"; String b = "bb"; System.out.println (a.hashcode ()); System.out.println (B.HashCode ()); }}Hasil output:
Utama@2A139A55 2A139A55 2112 2112
Secara umum, saat menulis ulang fungsi yang sama, Anda juga perlu menulis ulang fungsi kode hash. Mengapa ini?
Mari kita lihat contoh ini, mari kita buat karyawan kelas sederhana
karyawan kelas publik {private integer ID; Private String FirstName; Private String LastName; departemen string pribadi; Integer publik getId () {return id; } public void setid (integer id) {this.id = id; } public String getFirstName () {return firstName; } public void setFirstName (String firstName) {this.firstName = firstName; } public String getLastName () {return lastName; } public void setLastName (String LastName) {this.LastName = LastName; } public string getDepartment () {return department; } public void setDepartment (string department) {this.department = department; }}Kelas karyawan di atas hanya memiliki beberapa properti dan getters dan setter yang sangat mendasar. Sekarang pertimbangkan situasi di mana Anda perlu membandingkan dua karyawan.
kelas publik equalstest {public static void main (string [] args) {karyawan e1 = karyawan baru (); Karyawan E2 = Karyawan Baru (); e1.setid (100); e2.setid (100); // mencetak false di konsol system.out.println (e1.equals (e2)); }}Tidak ada keraguan bahwa program di atas akan menghasilkan false, tetapi pada kenyataannya, dua objek di atas mewakili melalui karyawan. Logika bisnis yang sebenarnya berharap bahwa kita kembali benar.
Untuk mencapai ini, kita perlu menulis ulang metode yang sama.
public boolean sama (objek o) {if (o == null) {return false; } if (o == ini) {return true; } if (getClass ()! = o.getClass ()) {return false; } Karyawan e = (karyawan) o; return (this.getId () == e.getId ());} Tambahkan metode ini ke kelas di atas dan eauqlstest akan menghasilkan true.
Jadi apakah kita selesai? Tidak, mari kita ubah metode pengujian dan lihat.
Impor java.util.hashset; impor java.util.set; kelas publik equalstest {public static void main (string [] args) {karyawan e1 = karyawan baru (); karyawan E2 = karyawan baru (); e1.setid (100); e2.setid (100); // prints '); e1system (100); e2.setid (100); // cetak (); e1system. = hashset baru <eployee> (); karyawan.add (e1); karyawan.add (e2); // mencetak dua objekssystem.out.println (karyawan);}Program di atas menghasilkan dua hasil. Jika dua objek karyawan sama dengan pengembalian true, hanya satu objek yang harus disimpan dalam set. Apa masalahnya?
Kami lupa metode hashcode kedua (). Seperti yang dikatakan JDK Javadoc, jika Anda menulis ulang metode Equals (), Anda harus menulis ulang metode hashcode (). Mari kita tambahkan metode berikut dan program akan dijalankan dengan benar.
@Override public int hashCode () {final int prime = 31; Hasil int = 1; Hasil = hasil prime * + getId (); hasil pengembalian; }Hal -hal yang perlu diingat
Cobalah untuk memastikan bahwa properti yang sama dari objek digunakan untuk menghasilkan dua metode: hashCode () dan equals (). Dalam kasus kami, kami menggunakan ID karyawan.
Metode EQAULS harus konsisten (jika objek tidak dimodifikasi, setara harus mengembalikan nilai yang sama)
Setiap saat selama A.Equals (b), a.hashcode () harus sama dengan b.hashcode ().
Keduanya harus ditulis ulang secara bersamaan.
Meringkaskan
Di atas adalah semua tentang pemahaman mendalam artikel ini tentang metode kode hashcode di Java, dan saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!