Saya pernah mendengar di kelas gelar saya bahwa a HashTable
akan menempatkan entri baru ke dalam ember 'berikutnya yang tersedia' jika entri Kunci baru bertabrakan dengan yang lain.
Bagaimana HashTable
masih mengembalikan Nilai yang benar jika tabrakan ini terjadi saat memanggil satu punggung dengan kunci tabrakan?
Saya berasumsi bahwa tipe Keys
are String
dan hashCode()
mengembalikan default yang dihasilkan oleh katakanlah Java.
Jika saya menerapkan fungsi hashing saya sendiri dan menggunakannya sebagai bagian dari tabel pencarian (yaitu a HashMap
atau Dictionary
), strategi apa yang ada untuk menangani tabrakan?
Saya bahkan pernah melihat not yang berhubungan dengan bilangan prima! Informasi tidak begitu jelas dari pencarian Google.
Ketika Anda berbicara tentang "Tabel Hash akan menempatkan entri baru ke dalam keranjang 'berikutnya yang tersedia' jika entri Kunci baru bertabrakan dengan yang lain.", Anda berbicara tentang strategi pengalamatan terbuka resolusi tabrakan dari tabel hash.
Ada beberapa strategi untuk tabel hash untuk mengatasi tabrakan.
Jenis metode besar pertama mengharuskan kunci (atau penunjuk ke mereka) disimpan dalam tabel, bersama dengan nilai terkait, yang selanjutnya mencakup:
Metode penting lainnya untuk menangani tabrakan adalah dengan mengubah ukuran dinamis , yang selanjutnya memiliki beberapa cara:
EDIT : yang di atas dipinjam dari wiki_hash_table , di mana Anda harus melihat-lihat untuk mendapatkan info lebih lanjut.
sumber
Ada beberapa teknik yang tersedia untuk menangani tabrakan. Saya akan menjelaskan beberapa di antaranya
Chaining: Dalam chaining kita menggunakan indeks array untuk menyimpan nilai. Jika kode hash dari nilai kedua juga menunjuk ke indeks yang sama maka kami mengganti nilai indeks itu dengan daftar tertaut dan semua nilai yang menunjuk ke indeks itu disimpan dalam daftar tertaut dan poin indeks larik aktual ke kepala daftar tertaut. Tetapi jika hanya ada satu kode hash yang menunjuk ke indeks array maka nilainya langsung disimpan dalam indeks itu. Logika yang sama diterapkan saat mengambil nilai. Ini digunakan di Java HashMap / Hashtable untuk menghindari tabrakan.
Linear probing: Teknik ini digunakan ketika kita memiliki lebih banyak indeks dalam tabel daripada nilai yang akan disimpan. Teknik probing linier bekerja pada konsep terus bertambah sampai Anda menemukan slot kosong. Kode pseudo terlihat seperti ini:
Teknik hashing ganda: Dalam teknik ini kita menggunakan dua fungsi hashing h1 (k) dan h2 (k). Jika slot pada h1 (k) terisi maka fungsi hashing kedua h2 (k) digunakan untuk menaikkan indeks. Pseudo-code terlihat seperti ini:
Teknik probing linier dan hashing ganda adalah bagian dari teknik pengalamatan terbuka dan hanya dapat digunakan jika slot yang tersedia lebih dari jumlah item yang akan ditambahkan. Dibutuhkan lebih sedikit memori daripada chaining karena tidak ada struktur tambahan yang digunakan di sini tetapi lambat karena banyak pergerakan terjadi hingga kami menemukan slot kosong. Juga dalam teknik pengalamatan terbuka ketika sebuah item dikeluarkan dari slot kami meletakkan batu nisan untuk menunjukkan bahwa item tersebut dihapus dari sini itulah mengapa itu kosong.
Untuk informasi lebih lanjut lihat situs ini .
sumber
Saya sangat menyarankan Anda untuk membaca posting blog ini yang muncul di HackerNews baru-baru ini: Bagaimana HashMap bekerja di Java
Singkatnya, jawabannya adalah
sumber
Ini sebenarnya tidak benar, setidaknya untuk Oracle JDK (ini adalah detail implementasi yang dapat bervariasi antara implementasi API yang berbeda). Sebaliknya, setiap keranjang berisi daftar entri yang ditautkan sebelum Java 8, dan pohon yang seimbang di Java 8 atau lebih tinggi.
Ini menggunakan
equals()
untuk menemukan entri yang benar-benar cocok.Ada berbagai strategi penanganan tabrakan dengan kelebihan dan kekurangan yang berbeda. Entri Wikipedia tentang tabel hash memberikan gambaran yang bagus.
sumber
Hashtable
danHashMap
di jdk 1.6.0_22 oleh Sun / Oracle.public V get(Object key)
sekarang (versi yang sama seperti di atas). Jika Anda menemukan versi tepat tempat daftar tertaut tersebut muncul, saya tertarik untuk mengetahuinya.Entry
objek yang ditautkan :localEntry = localEntry.next
e = e.next
tidak++index
. +1Pembaruan sejak Java 8: Java 8 menggunakan pohon yang seimbang untuk penanganan tabrakan, meningkatkan kasus terburuk dari O (n) ke O (log n) untuk pencarian. Penggunaan self-balanced tree diperkenalkan di Java 8 sebagai perbaikan atas chaining (digunakan hingga java 7), yang menggunakan linked-list, dan memiliki kasus terburuk O (n) untuk pencarian (karena perlu melintasi Daftar)
Untuk menjawab bagian kedua dari pertanyaan Anda, penyisipan dilakukan dengan memetakan elemen tertentu ke indeks tertentu dalam larik yang mendasari dari hashmap, namun, saat tabrakan terjadi, semua elemen harus tetap dipertahankan (disimpan dalam struktur data sekunder , dan tidak hanya diganti dalam larik yang mendasari). Ini biasanya dilakukan dengan membuat setiap komponen-array (slot) menjadi struktur data sekunder (alias keranjang), dan elemen ditambahkan ke keranjang yang berada di indeks-array yang diberikan (jika kunci belum ada di keranjang, di yang mana itu diganti).
Selama pencarian, kunci di-hash ke indeks-array yang sesuai, dan pencarian dilakukan untuk elemen yang cocok dengan kunci (tepat) dalam keranjang yang diberikan. Karena bucket tidak perlu menangani tabrakan (membandingkan kunci secara langsung), ini memecahkan masalah tabrakan, tetapi melakukannya dengan biaya harus melakukan penyisipan dan pencarian pada struktur data sekunder. Poin kuncinya adalah bahwa dalam peta hash, baik kunci maupun nilainya disimpan, dan bahkan jika hash bertabrakan, kunci akan dibandingkan secara langsung untuk persamaan (dalam keranjang), dan karenanya dapat diidentifikasi secara unik dalam keranjang.
Penanganan-benturan membawa kinerja penyisipan dan pencarian kasus terburuk dari O (1) dalam kasus tidak ada penanganan-tabrakan ke O (n) untuk rantai (daftar tertaut digunakan sebagai struktur data sekunder) dan O (log n) untuk pohon yang seimbang.
Referensi:
sumber
Ini akan menggunakan metode sama dengan untuk melihat apakah kunci ada bahkan dan terutama jika ada lebih dari satu elemen dalam keranjang yang sama.
sumber
Karena ada beberapa kebingungan tentang algoritma mana yang digunakan HashMap Java (dalam implementasi Sun / Oracle / OpenJDK), berikut cuplikan kode sumber yang relevan (dari OpenJDK, 1.6.0_20, di Ubuntu):
Metode ini (kutipan dari baris 355 hingga 371) dipanggil saat mencari entri dalam tabel, misalnya dari
get()
,containsKey()
dan beberapa lainnya. Perulangan for di sini melewati daftar tertaut yang dibentuk oleh objek entri.Berikut kode untuk objek entri (baris 691-705 + 759):
Tepat setelah ini muncul
addEntry()
metode:Ini menambahkan Entri baru di depan keranjang, dengan tautan ke entri pertama yang lama (atau nol, jika tidak ada). Demikian pula,
removeEntryForKey()
metode ini menelusuri daftar dan menangani hanya menghapus satu entri, membiarkan sisa daftar tetap utuh.Jadi, berikut adalah daftar entri yang ditautkan untuk setiap keranjang, dan saya sangat ragu ini berubah dari
_20
menjadi_22
, karena ini seperti ini dari 1.2 ke atas.(Kode ini adalah (c) 1997-2007 Sun Microsystems, dan tersedia di bawah GPL, tetapi untuk menyalin lebih baik gunakan file asli, yang terdapat di src.zip di setiap JDK dari Sun / Oracle, dan juga di OpenJDK.)
sumber
berikut adalah implementasi tabel hash yang sangat sederhana di java. hanya dalam implementasi
put()
danget()
, tetapi Anda dapat dengan mudah menambahkan apa pun yang Anda suka. itu bergantung padahashCode()
metode java yang diimplementasikan oleh semua objek. Anda dapat dengan mudah membuat antarmuka Anda sendiri,dan memaksanya untuk diterapkan oleh tombol jika Anda mau.
sumber
Ada berbagai metode untuk resolusi tabrakan, beberapa di antaranya adalah Rantai Terpisah, Pengalamatan terbuka, hashing Robin Hood, Cuckoo Hashing, dll.
Java menggunakan Rangkaian Terpisah untuk menyelesaikan tabrakan dalam tabel Hash. Berikut ini tautan bagus tentang bagaimana hal itu terjadi: http://javapapers.com/core-java/java-hashtable/
sumber