Nilai hashCode dari Java String dikomputasi sebagai ( String.hashCode () ):
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
Apakah ada keadaan (katakanlah versi JVM, vendor, dll.) Di mana ungkapan berikut akan dinilai salah?
boolean expression = "This is a Java string".hashCode() == 586653468
Pembaruan # 1: Jika Anda mengklaim bahwa jawabannya adalah "ya, ada beberapa keadaan" - maka tolong berikan contoh konkret kapan "Ini adalah string Java" .hashCode ()! = 586653468. Cobalah untuk menjadi spesifik / konkret mungkin.
Pembaruan # 2: Kita semua tahu bahwa mengandalkan detail implementasi hashCode () secara umum buruk. Namun, saya sedang berbicara secara khusus tentang String.hashCode () - jadi harap tetap fokus pada String.hashCode (). Object.hashCode () sama sekali tidak relevan dalam konteks pertanyaan ini.
Jawaban:
Saya bisa melihat dokumentasi itu sejauh Jawa 1.2.
Meskipun memang benar bahwa secara umum Anda tidak harus bergantung pada implementasi kode hash yang tetap sama, namun sekarang perilaku tersebut didokumentasikan
java.lang.String
, sehingga mengubahnya akan dianggap melanggar kontrak yang ada.Sedapat mungkin, Anda tidak harus bergantung pada kode hash yang tetap sama di semua versi dll - tetapi dalam pikiran saya
java.lang.String
adalah kasus khusus hanya karena algoritme telah ditentukan ... selama Anda bersedia untuk meninggalkan kompatibilitas dengan rilis sebelum Algoritma ditentukan, tentu saja.sumber
Saya menemukan sesuatu tentang JDK 1.0 dan 1.1 dan> = 1.2:
Sesuatu yang berbeda, karena Anda tampaknya memerlukan nomor: Bagaimana kalau menggunakan CRC32 atau MD5 alih-alih kode hash dan Anda bisa melakukannya - tidak ada diskusi dan tidak ada kekhawatiran sama sekali ...
sumber
Anda tidak boleh mengandalkan kode hash yang sama dengan nilai tertentu. Hanya saja itu akan mengembalikan hasil yang konsisten dalam eksekusi yang sama. Dokumen API mengatakan sebagai berikut:
EDIT Karena javadoc untuk String.hashCode () menentukan bagaimana kode hash String dihitung, setiap pelanggaran ini akan melanggar spesifikasi API publik.
sumber
Seperti dikatakan di atas, secara umum Anda tidak harus bergantung pada kode hash dari kelas yang tetap sama. Perhatikan bahwa bahkan menjalankan aplikasi yang sama pada VM yang sama dapat menghasilkan nilai hash yang berbeda. AFAIK fungsi hash Sun JVM menghitung hash yang sama pada setiap proses, tapi itu tidak dijamin.
Perhatikan bahwa ini bukan teori. Fungsi hash untuk java.lang.String diubah di JDK1.2 (hash lama memiliki masalah dengan string hirarkis seperti URL atau nama file, karena cenderung menghasilkan hash yang sama untuk string yang hanya berbeda di akhir).
java.lang.String adalah kasus khusus, karena algoritme dari kode hash () didokumentasikan, jadi Anda mungkin bisa mengandalkan itu. Saya masih menganggapnya sebagai praktik buruk. Jika Anda memerlukan algoritma hash dengan properti khusus dan terdokumentasi, cukup tulis satu :-).
sumber
Masalah lain (!) Yang perlu dikhawatirkan adalah kemungkinan perubahan implementasi antara versi Java awal / akhir. Saya tidak percaya detail implementasi diatur dalam batu, dan berpotensi upgrade ke versi Java di masa depan dapat menyebabkan masalah.
Intinya adalah, saya tidak akan bergantung pada implementasi
hashCode()
.Mungkin Anda bisa menyoroti masalah apa yang sebenarnya ingin Anda selesaikan dengan menggunakan mekanisme ini, dan itu akan menyoroti pendekatan yang lebih cocok.
sumber
switch
pernyataan atas string mengkompilasi ke kode yang mengandalkan kode hash tetap tertentu, perubahan padaString
algoritma kode hash pasti akan memecahkan kode yang ada ...Hanya untuk menjawab pertanyaan Anda dan tidak melanjutkan diskusi. Implementasi Apache Harmony JDK tampaknya menggunakan algoritma yang berbeda, setidaknya terlihat sangat berbeda:
Sun JDK
Apache Harmony
Jangan ragu untuk memeriksanya sendiri ...
sumber
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
Kecuali saya salah, ini karena Android menggunakan implementasi objek String oleh Sun tanpa perubahan.Jika Anda khawatir tentang perubahan dan kemungkinan VM yang tidak kompatibel, cukup salin implementasi kode hash yang ada ke kelas utilitas Anda sendiri, dan gunakan itu untuk menghasilkan kode hash Anda.
sumber
Kode hash akan dihitung berdasarkan nilai ASCII dari karakter dalam String.
Ini adalah implementasi di Kelas String adalah sebagai berikut
Tabrakan dalam kode hash tidak dapat dihindari. Misalnya, string "Ea" dan "FB" memberikan kode hash yang sama dengan 2236
sumber