Rumah > Peranti teknologi > industri IT > Cara melaksanakan hashcode Java ' s dengan betul

Cara melaksanakan hashcode Java ' s dengan betul

尊渡假赌尊渡假赌尊渡假赌
Lepaskan: 2025-02-18 10:46:14
asal
621 orang telah melayarinya

SitePoint meneroka dunia Java: Jemput pemaju Java untuk menyumbang

How to Implement Java's hashCode Correctly

SitePoint terus mengembangkan medan kandungannya dan akan memberi tumpuan kepada Java dalam masa terdekat. Jika anda seorang pemaju Java yang berpengalaman dan ingin menyumbang kepada kandungan Java kami, sila hubungi kami untuk berkongsi idea topik yang ingin anda tulis.

pelaksanaan kaedah

dan equals yang betul dalam java hashCode

anda telah melaksanakan kaedah

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 sepadan
    mesti diwujudkan untuk memastikan ketepatan dan konsistensi menyimpan dan mengambil objek dalam koleksi berasaskan hash.
  • Apabila melaksanakan equals, 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.
  • Kod hash berkaitan dengan pengoptimuman prestasi, jadi anda tidak boleh meletakkan terlalu banyak usaha ke dalam hash kecuali analisis prestasi menunjukkan penambahbaikan diperlukan. 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.
  • dan
  • kaedah

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

Pembolehubah

adalah benar, kerana walaupun contoh "B" tidak sama (sekali lagi mengabaikan residensi rentetan), mereka sama. equals

Walau bagaimanapun, membandingkan setiap elemen dengan contoh yang diluluskan kepada kaedah
List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
adalah tidak cekap, manakala kelas struktur data menggunakan kaedah yang lebih efisien. Daripada membandingkan contoh yang diminta dengan setiap elemen yang mereka ada, mereka menggunakan jalan pintas untuk mengurangkan bilangan contoh yang mungkin sama, dan kemudian membandingkan hanya contoh tersebut.

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

adalah wakil yang paling terkenal.

contains mereka biasanya bekerja seperti berikut:

  • Apabila menambah elemen, kod hashnya digunakan untuk mengira indeks dalam array dalaman (dipanggil baldi).
  • Jika unsur -unsur yang tidak sama rata mempunyai kod hash yang sama, mereka berakhir dalam baldi yang sama dan mesti dibundel bersama -sama, contohnya dengan menambahkannya ke senarai.
  • Apabila lulus contoh ke kaedah 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 objek equals 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 ke hashCode 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 kaedah hashCode 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");
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

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

Pilih medan

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");
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

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

Ini boleh menyebabkan limpahan, tetapi ini tidak menyebabkan pengecualian di Jawa, jadi tidak ada masalah besar.
List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

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

kaedah:

hashCode

Gunakan medan yang sama (atau subsetnya) seperti yang digunakan dalam kaedah
    .
  • equals Adalah lebih baik untuk tidak memasukkan medan berubah -ubah.
  • Pertimbangkan tidak memanggil kaedah
  • pada koleksi.
  • hashCode Gunakan algoritma biasa melainkan pola data input adalah sebaliknya.
  • ingat, kaedah
berkaitan dengan prestasi, jadi jangan buang terlalu banyak tenaga kecuali analisis prestasi menunjukkan ia perlu.

hashCode Soalan Lazim pada pelaksanaan Java

kaedah yang betul (Soalan Lazim)

hashCode Apakah kepentingan kaedah

di Java?

hashCode() Kaedah

di Java adalah fungsi terbina dalam yang mengembalikan nilai integer. Ia digunakan terutamanya untuk koleksi berasaskan hash (seperti

, 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()

Bagaimana kaedah 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.

Apakah konvensyen antara kaedah

dan equals() dalam hashCode() di Java?

Konvensyen antara

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.

Bagaimana untuk menulis semula kaedah 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.

Apakah konflik hash dan bagaimana untuk mengelakkannya?

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.

Kenapa kaedah 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.

Di Java, bolehkah dua objek yang tidak sama rata mempunyai 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.

Apa yang berlaku jika saya tidak menulis semula kaedah 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?

Kaedah

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.

Bolehkah saya menggunakan kaedah 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!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan