1、“你知道HashMap的工作原理嗎肖粮?” “你知道HashMap的get()方法的工作原理嗎桥帆?”
HashMap是基于hashing的原理,我們使用put(key, value)存儲對象到HashMap中谆构,使用get(key)從HashMap中獲取對象。當我們給put()方法傳遞鍵和值時算柳,我們先對鍵調用hashCode()方法低淡,返回的hashCode用于找到bucket位置來儲存Entry對象∷蚕睿”這里關鍵點在于指出蔗蹋,HashMap是在bucket中儲存鍵對象和值對象,作為Map.Entry囱淋。
2猪杭、“當兩個對象的hashcode相同會發(fā)生什么?”
因為hashcode相同妥衣,所以它們的bucket位置相同皂吮,‘碰撞’會發(fā)生。因為HashMap使用LinkedList存儲對象税手,這個Entry(包含有鍵值對的Map.Entry對象)會存儲在LinkedList中蜂筹。(當向 HashMap 中添加 key-value 對,由其 key 的 hashCode() 返回值決定該 key-value 對(就是 Entry 對象)的存儲位置芦倒。當兩個 Entry 對象的 key 的 hashCode() 返回值相同時艺挪,將由 key 通過 eqauls() 比較值決定是采用覆蓋行為(返回 true),還是產生 Entry 鏈(返回 false)兵扬。)
3麻裳、“如果兩個鍵的hashcode相同,你如何獲取值對象器钟?”
當我們調用get()方法津坑,HashMap會使用鍵對象的hashcode找到bucket位置,然后獲取值對象傲霸。如果有兩個值對象儲存在同一個bucket疆瑰,將會遍歷LinkedList直到找到值對象。找到bucket位置之后昙啄,會調用keys.equals()方法去找到LinkedList中正確的節(jié)點穆役,最終找到要找的值對象。(當程序通過 key 取出對應 value 時跟衅,系統(tǒng)只要先計算出該 key 的 hashCode() 返回值,在根據該 hashCode 返回值找出該 key 在 table 數(shù)組中的索引播歼,然后取出該索引處的 Entry伶跷,最后返回該 key 對應的 value 即可掰读。)
4、“如果HashMap的大小超過了負載因子(load factor)定義的容量叭莫,怎么辦蹈集?”
當一個map填滿了75%的bucket時候,和其它集合類(如ArrayList等)一樣雇初,將會創(chuàng)建原來HashMap大小的兩倍的bucket數(shù)組拢肆,來重新調整map的大小,并將原來的對象放入新的bucket數(shù)組中靖诗。這個過程叫作rehashing郭怪,因為它調用hash方法找到新的bucket位置。
5刊橘、“你了解重新調整HashMap大小存在什么問題嗎鄙才?”
當重新調整HashMap大小的時候,確實存在條件競爭促绵,因為如果兩個線程都發(fā)現(xiàn)HashMap需要重新調整大小了攒庵,它們會同時試著調整大小。在調整大小的過程中败晴,存儲在LinkedList中的元素的次序會反過來浓冒,因為移動到新的bucket位置的時候,HashMap并不會將元素放在LinkedList的尾部尖坤,而是放在頭部稳懒,這是為了避免尾部遍歷(tail traversing)。如果條件競爭發(fā)生了糖驴,那么就死循環(huán)了僚祷。這個時候,你可以質問面試官贮缕,為什么這么奇怪辙谜,要在多線程的環(huán)境下使用HashMap呢?