Map的Key你真的了解嗎?
何類作為Map的Key?為什么HashMap中String、Integer這樣的包裝類適合作為Key?如果使用Object作為HashMap的Key,應該怎么辦?” 這個問題看似簡單,但實際上涉及到HashMap的核心機制,面試中說得清楚絕對能讓面試官眼前一亮!
話不多說,讓我們通過一個小故事,邊學邊聊。
初識問題:能否使用任何類作為Map的Key?
故事從小明找工作說起。小明在面試時被問到:“你能用任何類作為Map的Key嗎?”
小明想了想,答:“理論上可以吧,但會有坑。”
沒錯,理論上任何類都可以作為Map的Key。但是!能否真正高效和正確地使用,得滿足兩個條件:
- 必須重寫hashCode()方法:這是因為HashMap基于哈希表實現,hashCode()決定了對象的存儲位置。
- 必須重寫equals()方法:當兩個對象的hashCode相同,HashMap會使用equals()方法來判斷它們是否真的相等。
如果你用的類沒有重寫這兩個方法,HashMap就可能無法正確判斷Key是否相等,導致奇怪的行為。比如,明明存進去了,卻取不出來。
為什么String和Integer適合作為Key?
接著,面試官進一步追問:“那為什么String和Integer這樣的包裝類適合作為Key呢?”
小明頓時慌了,但冷靜下來,他回憶起學過的知識,侃侃而談。
String
- String的hashCode()實現簡單明了,基于內容計算哈希值。
- 它的equals()方法也是內容比較,完全符合HashMap的需求。
- 不可變性:String是不可變類,哈希值一旦計算,就不會因內容變化而失效。
Integer
- Integer的hashCode()直接返回它的值,簡單高效。
- equals()也是基于值的比較。
- 同樣是不可變的包裝類,Key的狀態不會因外部修改而改變。
對比之下,如果你使用一個可變對象作為Key,比如一個List,情況會變得復雜。如果在存入HashMap后,你修改了List的內容,它的hashCode就會改變,導致HashMap無法正確找到存儲的位置。
如果使用Object作為Key,該怎么辦?
這時,面試官繼續刁難:“假如我想用自己的類Person作為Key呢?”
小明心里有底了,他微微一笑:“那就得自己實現hashCode()和equals()方法了。”
如何實現?
以下是小明舉的例子:
圖片
- hashCode():使用Objects.hash()方法將name和age的值組合成一個哈希值,保證哈希分布的均勻性。
- equals():確保當兩個對象的name和age都相同時,它們被認為是相等的。
避坑指南:Key需要注意哪些問題?
1、不可變性
Key最好是不可變的(如String和Integer),否則會導致數據一致性問題。
2、重寫規則一致
如果你重寫了equals(),就必須重寫hashCode(),并保證規則一致:
- 如果兩個對象相等(equals()返回true),它們的hashCode必須相等。
- 如果兩個對象不相等,它們的hashCode盡量不同。
3、合理選擇Key
如果使用復雜對象作為Key,確保它的字段值不會頻繁變動,否則建議使用唯一標識符(如ID)。
總結
面試結束后,小明總結道:
- 能否使用任何類作為Map的Key?:可以,但必須保證重寫hashCode()和equals()方法。
- 為什么String和Integer適合作為Key?:它們有良好的hashCode()和equals()實現,并且是不可變類。
- 如果使用自定義類作為Key?:重寫hashCode()和equals()方法,確保Key的唯一性和一致性。