Saya setuju dengan:
- kompleksitas umum yang diamortisasi dari O (1)
hashCode()
implementasi yang buruk dapat mengakibatkan beberapa tabrakan, yang berarti bahwa dalam kasus terburuk setiap objek pergi ke ember yang sama, sehingga O ( N ) jika setiap ember didukung oleh a List
.
- sejak Java 8,
HashMap
secara dinamis menggantikan Nodes (daftar tertaut) yang digunakan di setiap bucket dengan TreeNodes (pohon merah-hitam ketika daftar menjadi lebih besar dari 8 elemen) yang menghasilkan kinerja terburuk O ( logN ).
Tapi, ini BUKAN kebenaran sepenuhnya jika kita ingin 100% tepat. Implementasi hashCode()
dan jenis kunci Object
(tidak berubah / di-cache atau menjadi Koleksi) juga dapat memengaruhi kompleksitas nyata dalam istilah yang ketat.
Mari kita asumsikan tiga kasus berikut:
HashMap<Integer, V>
HashMap<String, V>
HashMap<List<E>, V>
Apakah mereka memiliki kompleksitas yang sama? Nah, kompleksitas amortisasi yang pertama adalah, seperti yang diharapkan, O (1). Tetapi, untuk sisanya, kita juga perlu menghitung hashCode()
elemen pencarian, yang berarti kita mungkin harus melintasi array dan daftar dalam algoritma kita.
Mari kita asumsikan bahwa ukuran semua array / daftar di atas adalah k . Kemudian, HashMap<String, V>
dan HashMap<List<E>, V>
akan ada O (k) kompleksitas diamortisasi dan juga, O ( k + logN ) kasus terburuk di Java8.
* Perhatikan bahwa menggunakan String
kunci adalah kasus yang lebih kompleks, karena tidak dapat diubah dan Java menyimpan hasil cache hashCode()
dalam variabel pribadi hash
, jadi itu hanya dihitung sekali.
/** Cache the hash code for the string */
private int hash; // Default to 0
Tapi, di atas juga memiliki kasus terburuknya sendiri, karena String.hashCode()
implementasi Java sedang memeriksa hash == 0
sebelum komputasi hashCode
. Tapi hei, ada String non-kosong yang menghasilkan a hashcode
nol, seperti "f5a5a608", lihat di sini , dalam hal ini memoisasi mungkin tidak membantu.