SitePoint meneroka dunia Java: Jemput pemaju Java untuk menyumbang
pelaksanaan kaedah
dan equals
yang betul dalam java hashCode
untuk kelas anda? Hebat! Tetapi anda juga perlu melaksanakan kaedah equals
. Mari kita faham mengapa dan bagaimana melaksanakannya dengan betul.
Mata Utama: hashCode
Di Java, objek yang sama harus mempunyai kod hash yang sama. Oleh itu, jika kaedah
ditulis semula, pelaksanaan yang sepadanequals
, medan yang sama yang digunakan dalam kaedah hashCode
hendaklah digunakan. Cuba untuk mengelakkan menggunakan bidang dan koleksi yang boleh berubah, kerana ini boleh menyebabkan masalah prestasi. hashCode
equals
Perlanggaran hash (dua objek yang berbeza mempunyai kod hash yang sama) dapat dikurangkan dengan meningkatkan algoritma hash dan menggunakan nombor perdana yang lebih besar sebagai pengganda. Ini membantu untuk mengedarkan kod hash yang lebih merata dalam set, mengurangkan kemungkinan konflik hash dan memastikan pengambilan data yang lebih cepat. Walaupun kaedah equals
adalah munasabah dari perspektif umum, kaedah hashCode
lebih teknikal. Sebenarnya, ia hanya satu perincian pelaksanaan untuk meningkatkan prestasi.
Kebanyakan struktur data menggunakan kaedah equals
untuk memeriksa sama ada ia mengandungi elemen. Contohnya: hashCode
adalah benar, kerana walaupun contoh "B" tidak sama (sekali lagi mengabaikan residensi rentetan), mereka sama. equals
List<String> list = Arrays.asList("a", "b", "c"); boolean contains = list.contains("b");
contains
Pintasan ini adalah kod hash, yang boleh dianggap sebagai kesamaan objek yang akan dikurangkan kepada nilai integer. Contohnya dengan kod hash yang sama tidak semestinya sama, tetapi contoh yang sama mempunyai kod hash yang sama. (Atau sepatutnya mempunyai kod hash yang sama, yang akan kita bincangkan kemudian.) Struktur data sedemikian biasanya dinamakan selepas nama teknikal mereka, yang mengandungi "hash" di mana
contains
mereka biasanya bekerja seperti berikut:
contains
, baldi dikira menggunakan kod hashnya. Hanya unsur -unsur di dalamnya dibandingkan dengan contohnya. dengan cara ini, melaksanakan kaedah contains
hanya memerlukan sangat sedikit, idealnya tanpa perbandingan equals
.
seperti kaedah equals
, kaedah hashCode
juga ditakrifkan dalam kelas Object
.
Berfikir tentang hash
Jika kaedah hashCode
digunakan sebagai jalan pintas untuk menentukan kesamaan, maka hanya ada satu perkara yang kita harus benar -benar peduli: objek yang sama harus mempunyai kod hash yang sama.
Ini juga mengapa jika kita menulis semula kaedah equals
, kita perlu membuat pelaksanaan hashCode
yang sepadan! Jika tidak, perkara yang sama mengikut pelaksanaan kami mungkin tidak mempunyai kod hash yang sama, kerana mereka menggunakan pelaksanaan kelas Object
.
hashCode
Perjanjian kaedah
Cite Sumber Code:
hashCode
Perjanjian umum kaedah adalah:
- Apabila ia dipanggil pada objek yang sama beberapa kali semasa pelaksanaan aplikasi Java, kaedah
hashCode
mesti sentiasa mengembalikan integer yang sama, dengan syarat bahawa maklumat yang digunakan dalam perbandingan objekequals
tidak diubah suai. Integer ini tidak perlu konsisten antara pelaksanaan satu aplikasi dan pelaksanaan lain aplikasi yang sama.- Jika dua objek adalah sama mengikut kaedah
equals(Object)
, panggilan kehashCode
kaedah mesti menghasilkan hasil integer yang sama pada setiap dua objek.- Jika kedua -dua objek tidak sama mengikut kaedah
equals(Object)
, anda tidak perlu memanggil kaedahhashCode
pada kedua -dua objek yang mesti menghasilkan hasil integer yang berbeza. Walau bagaimanapun, pengaturcara harus menyedari bahawa menghasilkan hasil integer yang berbeza untuk objek yang tidak sama rata dapat meningkatkan prestasi jadual hash.
Titik pertama mencerminkan atribut konsistensi kaedah equals
, dan titik kedua adalah keperluan yang telah kita lalui di atas. Titik ketiga menggambarkan butiran penting yang akan kita bincangkan kemudian.
pelaksanaan hashCode
kaedah
Pelaksanaan Person.hashCode
yang sangat mudah adalah seperti berikut:
List<String> list = Arrays.asList("a", "b", "c"); boolean contains = list.contains("b");
Kod hash manusia dikira dengan mengira kod hash bidang yang berkaitan dan menggabungkannya bersama -sama. Kedua -duanya ditinggalkan ke fungsi utiliti Objects
untuk diproses. hash
tetapi bidang mana yang berkaitan? Keperluan ini membantu menjawab soalan ini: Jika objek yang sama mesti mempunyai kod hash yang sama, pengiraan kod hash tidak boleh mengandungi sebarang medan yang tidak digunakan untuk pemeriksaan kesamaan. (Jika tidak, hanya dua objek yang berbeza pada bidang ini akan sama, tetapi mempunyai kod hash yang berbeza.)
Oleh itu, set medan yang digunakan untuk hashing harus menjadi subset dari set medan yang digunakan untuk kesamaan. Secara lalai, kedua -duanya akan menggunakan medan yang sama, tetapi terdapat beberapa butiran untuk dipertimbangkan.Konsistensi
Pertama sekali, terdapat keperluan konsisten. Ia harus ditafsirkan dengan ketat. Walaupun ia membolehkan kod hash berubah apabila beberapa bidang berubah (yang sering tidak dapat dielakkan untuk kelas yang boleh berubah), struktur data hash tidak siap untuk senario ini.
Seperti yang kita lihat di atas, kod hash digunakan untuk menentukan baldi elemen. Walau bagaimanapun, jika medan berkaitan hash berubah, hash tidak dikira semula dan array dalaman tidak dikemas kini.
Ini bermakna bahawa pertanyaan berikutnya menggunakan objek yang sama atau bahkan menggunakan contoh yang sama akan gagal! Struktur data mengira kod hash semasa (tidak seperti kod hash yang digunakan untuk menyimpan contoh) dan mencarinya dalam baldi yang salah.
KESIMPULAN: Adalah lebih baik untuk tidak menggunakan medan berubah untuk pengiraan kod hash!
Prestasi
Bilangan kali kod hash dikira mungkin kira -kira sama dengan bilangan kali
kaedah dipanggil. Ini mungkin berlaku dalam bahagian prestasi kritikal kod, jadi masuk akal untuk mempertimbangkan prestasi. Dan tidak seperti kaedah, terdapat lebih banyak ruang untuk pengoptimuman di sini. equals
equals
Kecuali algoritma kompleks digunakan atau banyak bidang yang terlibat, kos aritmetik untuk menggabungkan kod hashnya adalah remeh sebagai kos yang tidak dapat dielakkan. Tetapi pertimbangkan sama ada semua bidang perlu dimasukkan dalam pengiraan! Khususnya, set itu harus ragu -ragu. Sebagai contoh, senarai dan koleksi akan mengira nilai hash untuk setiap elemen mereka. Sama ada mereka perlu dipanggil harus dipertimbangkan berdasarkan keadaan.
Jika prestasi adalah kritikal, menggunakan
juga tidak boleh menjadi pilihan terbaik, kerana ia memerlukan membuat array untuk parameternya yang boleh berubah.
Objects.hash
Tetapi peraturan umum tentang pengoptimuman masih berlaku: Jangan mengoptimumkan terlalu awal! Menggunakan algoritma kod hash biasa, mungkin meninggalkan set inklusi dan pengoptimuman hanya dilakukan selepas analisis prestasi menunjukkan bahawa terdapat kemungkinan peningkatan.
konflik
mengambil semua usaha anda untuk meneruskan prestasi, jadi bagaimana dengan pelaksanaan ini?
Ia mesti cepat. Dan objek yang sama akan mempunyai kod hash yang sama, jadi kami juga baik dalam hal ini. Sebagai bonus, tiada bidang berubah -ubah yang terlibat!
List<String> list = Arrays.asList("a", "b", "c"); boolean contains = list.contains("b");
Tetapi ingat apa yang kita ada mengenai baldi sebelum ini? Dengan cara ini semua keadaan akan memasuki baldi yang sama! Ini biasanya menghasilkan senarai yang dipautkan yang memegang semua elemen, yang sangat buruk untuk prestasi. Sebagai contoh, setiap
panggilan mencetuskan imbasan linear senarai yang dipautkan.Oleh itu, kami mahu meminimumkan bilangan item dalam baldi yang sama! Algoritma yang mengembalikan kod hash yang sangat berbeza walaupun untuk objek yang sangat serupa adalah permulaan yang baik. Cara melaksanakan bergantung pada bahagian yang dipilih. Butiran lanjut yang kita sertakan dalam pengiraan, semakin besar kemungkinan bahawa kod hash adalah berbeza. Perhatikan bahawa ini adalah bertentangan dengan apa yang kita fikirkan tentang prestasi. Oleh itu, adalah menarik untuk diperhatikan bahawa menggunakan terlalu banyak
atau terlalu sedikit bidang boleh membawa kepada prestasi yang buruk. Satu lagi bahagian menghalang konflik adalah algoritma yang digunakan untuk benar -benar mengira hash.
Kirakan nilai hash
Cara paling mudah untuk mengira kod hash medan adalah untuk memanggil kaedah
di atasnya. Mereka boleh digabungkan secara manual. Algoritma yang biasa adalah bermula dengan nombor sewenang -wenangnya, kemudian berulang kali membiaknya dengan nombor lain (biasanya nombor perdana kecil) dan kemudian tambah hash medan:
hashCode
List<String> list = Arrays.asList("a", "b", "c"); boolean contains = list.contains("b");
Perhatikan bahawa walaupun algoritma hashing yang sangat baik boleh membawa kepada konflik yang luar biasa jika data input mempunyai corak tertentu. Sebagai contoh mudah, katakan kita mengira nilai hash titik dengan menambahkan koordinat x dan y titik. Ini kedengarannya cukup baik sehingga kita menyedari bahawa kita sering berurusan dengan mata pada garis lurus f (x) = -x, yang bermaksud bahawa untuk semua perkara ini, x y == 0. Konflik, banyak!
tetapi sekali lagi: Gunakan algoritma biasa dan jangan risau kecuali analisis prestasi menunjukkan masalah.
Ringkasan
kita telah melihat bahawa mengira kod hash adalah seperti memampatkan kesamaan ke dalam nilai integer: objek yang sama mesti mempunyai kod hash yang sama, dan atas sebab -sebab prestasi yang terbaik untuk berkongsi sama dengan beberapa objek yang tidak sama mungkin dengan hash yang sama dengan hash yang sama dengan hash yang sama dengan hash yang sama dengan hash yang sama dengan hash yang sama dengan hash yang sama kod.
Ini bermakna bahawa jika kaedah
ditulis semula, kaedah mesti selalu ditulis semula. equals
hashCode
pelaksanaan
hashCode
equals
Adalah lebih baik untuk tidak memasukkan medan berubah -ubah. hashCode
Gunakan algoritma biasa melainkan pola data input adalah sebaliknya.
hashCode
Soalan Lazim pada pelaksanaan Java
hashCode
Apakah kepentingan kaedah
hashCode()
Kaedah , hashCode()
dan HashMap
) untuk menyimpan dan mengambil objek dengan lebih cekap. Kaedah HashSet
berfungsi bersempena dengan kaedah HashTable
untuk memastikan setiap objek mempunyai pengenal unik. Ini membantu untuk mendapatkan data dengan cepat, terutamanya dalam koleksi besar, dengan itu meningkatkan prestasi aplikasi Java. hashCode()
hashCode()
berfungsi di Java? Kaedah hashCode()
dalam Java berfungsi dengan menghasilkan nilai integer yang mewakili alamat memori objek. Nilai ini digunakan sebagai nombor indeks objek dalam koleksi berasaskan hash. Apabila anda memanggil kaedah hashCode()
pada objek, ia menggunakan algoritma hashing untuk menghasilkan integer unik ini. Walau bagaimanapun, adalah penting untuk diperhatikan bahawa dua objek yang berbeza mungkin mempunyai hashCode
yang sama, yang dipanggil konflik hash.
equals()
dalam hashCode()
di Java? dan equals()
kaedah dalam hashCode()
di Java adalah satu set peraturan yang digunakan untuk menguruskan interaksi mereka. Konvensyen menyatakan bahawa jika dua objek adalah sama mengikut kaedah equals()
, panggilan ke hashCode()
kaedah mesti menghasilkan hasil integer yang sama pada setiap dua objek. Ini memastikan konsistensi dan ketepatan apabila menyimpan dan mengambil objek dalam koleksi berasaskan hash.
hashCode()
di Java? Tulis semula hashCode()
dalam kaedah Java termasuk menyediakan pelaksanaan anda sendiri yang mengembalikan integer unik untuk setiap objek. Ini boleh dicapai dengan menggunakan pembolehubah contoh objek dan pengganda utama. Nombor Perdana membantu secara merata mengedarkan kod hash dalam set, dengan itu mengurangkan kemungkinan perlanggaran hash.
Konflik hash bermaksud bahawa kaedah hashCode()
menghasilkan integer yang sama untuk dua objek yang berbeza. Jika tidak ditangani dengan betul, ini boleh menyebabkan kehilangan data. Untuk mengelakkan konflik hash, anda boleh meningkatkan algoritma hash untuk menghasilkan integer yang lebih unik. Selain itu, menggunakan nombor perdana yang lebih besar sebagai pengganda boleh membantu untuk mengedarkan lebih merata kod hash dalam set.
hashCode()
akan ditulis semula? menulis semula hashCode()
kaedah dapat meningkatkan prestasi aplikasi Java, terutama ketika berurusan dengan koleksi besar. Dengan menyediakan pelaksanaan anda sendiri, anda boleh menjana kod hash yang lebih unik dan sama rata, mengurangkan kemungkinan konflik hash dan memastikan pengambilan data yang lebih cepat.
hashCode
yang sama? Ya, di Java, dua objek yang tidak sama rata boleh mempunyai hashCode
yang sama. Ini dipanggil konflik hash. Walau bagaimanapun, dengan meningkatkan algoritma hashing dan menggunakan nombor perdana yang lebih besar sebagai pengganda, kemungkinan kejadian ini dapat dikurangkan.
hashCode()
? Jika anda tidak mengatasi kaedah hashCode()
, Java akan menggunakan pelaksanaan lalai, yang mungkin tidak memberikan kod hash yang unik untuk setiap objek. Ini boleh membawa kepada konflik hash dan pengambilan data yang lebih perlahan dalam koleksi berasaskan hash.
hashCode()
Bagaimana untuk meningkatkan prestasi aplikasi Java? hashCode()
meningkatkan prestasi aplikasi Java dengan menyediakan pengecam unik untuk setiap objek. Ini membolehkan data diambil lebih cepat dalam koleksi berasaskan hash, kerana objek boleh didapati secara langsung menggunakan kod hash objek tanpa mencari keseluruhan koleksi.
hashCode()
dalam koleksi bukan Hash? Walaupun kaedah hashCode()
digunakan terutamanya untuk koleksi berasaskan hash, ia juga boleh digunakan untuk koleksi berasaskan Hash. Walau bagaimanapun, faedah mungkin kurang jelas, kerana koleksi bukan Hash tidak bergantung pada kod hash untuk penyimpanan data dan pengambilan semula.
Atas ialah kandungan terperinci Cara melaksanakan hashcode Java ' s dengan betul. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!