HashMap
HashMap也是我們使用非常多的Collection逃糟,它是基于哈希表的 Map 接口的實(shí)現(xiàn)吼鱼,以key-value的形式存在。在HashMap中绰咽,key-value總是會(huì)當(dāng)做一個(gè)整體來處理菇肃,系統(tǒng)會(huì)根據(jù)hash算法來來計(jì)算key-value的存儲(chǔ)位置,我們總是可以通過key快速地存取募、取value琐谤。
實(shí)際上HashMap是一個(gè)“鏈表散列”HashMap底層實(shí)現(xiàn)還是數(shù)組,只是數(shù)組的每一項(xiàng)都是一條鏈玩敏。
HashMap保存數(shù)據(jù)的過程
首先判斷key是否為null斗忌,若為null质礼,則直接調(diào)用putForNullKey方法。若不為空則先計(jì)算key的hash值织阳,然后根據(jù)hash值搜索在table數(shù)組中的索引位置眶蕉,如果table數(shù)組在該位置處有元素,則通過比較是否存在相同的key唧躲,若存在則覆蓋原來key的value造挽,否則將該元素保存在鏈頭(最先保存的元素放在鏈尾)。若table在該處沒有元素弄痹,則直接保存刽宪。
put方法流程
當(dāng)我們調(diào)用put存值時(shí),HashMap首先會(huì)調(diào)用K的hashCode方法界酒,獲取哈希碼圣拄,通過哈希碼快速找到某個(gè)存放位置,這個(gè)位置可以被稱之為bucketIndex毁欣,通過hashCode的協(xié)定可以知道庇谆,如果hashCode不同,equals一定為false凭疮,如果hashCode相同饭耳,equals不一定為true。所以理論上执解,hashCode可能存在沖突的情況寞肖,有個(gè)專業(yè)名詞叫碰撞,當(dāng)碰撞發(fā)生時(shí)衰腌,計(jì)算出的bucketIndex也是相同的新蟆,這時(shí)會(huì)取到bucketIndex位置已存儲(chǔ)的元素,最終通過equals來比較右蕊,equals方法就是哈希碼碰撞時(shí)才會(huì)執(zhí)行的方法琼稻,所以前面說HashMap很少會(huì)用到equals。HashMap通過hashCode和equals最終判斷出K是否已存在饶囚,如果已存在帕翻,則使用新V值替換舊V值,并返回舊V值萝风,如果不存在 嘀掸,則存放新的鍵值對<K, V>到bucketIndex位置。
hashCode 的常規(guī)協(xié)定
在 Java 應(yīng)用程序執(zhí)行期間规惰,在同一對象上多次調(diào)用 hashCode 方法時(shí)睬塌,必須一致地返回相同的整數(shù),
前提是對象上 equals 比較中所用的信息沒有被修改。
如果根據(jù) equals(Object) 方法衫仑,兩個(gè)對象是相等的梨与,
那么在兩個(gè)對象中的每個(gè)對象上調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果。