最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

無(wú)語(yǔ)!四年社招還問(wèn)我Java Map集合

2023-06-27 21:50 作者:Java3y  | 我要投稿

面試官今天來(lái)講講Map吧,你對(duì)Map了解多少?就講JDK 1.8就好咯

候選者:Map在Java里邊是一個(gè)接口,常見(jiàn)的實(shí)現(xiàn)類有HashMap、LinkedHashMap、TreeMap和ConcurrentHashMap

候選者:在Java里邊,哈希表的結(jié)構(gòu)是數(shù)組+鏈表的方式。

候選者:HashMap底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組+鏈表/紅黑樹(shù)

候選者:LinkedHashMap底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組+鏈表/紅黑樹(shù)+雙向鏈表

候選者:TreeMap底層數(shù)據(jù)結(jié)構(gòu)是紅黑樹(shù)

候選者:而ConcurrentHashMap底層數(shù)據(jù)結(jié)構(gòu)也是數(shù)組+鏈表/紅黑樹(shù)


面試官我們先以HashMap開(kāi)始吧,你能講講當(dāng)你new一個(gè)HashMap的時(shí)候,會(huì)發(fā)生什么嗎?

候選者:HashMap有幾個(gè)構(gòu)造方法,但最主要的就是指定初始值大小和負(fù)載因子的大小。

候選者:如果我們不指定,默認(rèn)HashMap的大小為16,負(fù)載因子的大小為0.75

候選者:HashMap的大小只能是2次冪的,假設(shè)你傳一個(gè)10進(jìn)去,實(shí)際上最終HashMap的大小是16,你傳一個(gè)7進(jìn)去,HashMap最終的大小是8,具體的實(shí)現(xiàn)在tableSizeFor可以看到。

候選者:我們把元素放進(jìn)HashMap的時(shí)候,需要算出這個(gè)元素所在的位置(hash)。

候選者:在HashMap里用的是位運(yùn)算來(lái)代替取模,能夠更加高效地算出該元素所在的位置。

候選者:為什么HashMap的大小只能是2次冪,因?yàn)橹挥写笮?次冪時(shí),才能合理用位運(yùn)算替代取模。


候選者:而負(fù)載因子的大小決定著哈希表的擴(kuò)容和哈希沖突。

候選者:比如現(xiàn)在我默認(rèn)的HashMap大小為16,負(fù)載因子為0.75,這意味著數(shù)組最多只能放12個(gè)元素,一旦超過(guò)12個(gè)元素,則哈希表需要擴(kuò)容。

候選者:怎么算出是12呢?很簡(jiǎn)單,就是16*0.75。每次put元素進(jìn)去的時(shí)候,都會(huì)檢查HashMap的大小有沒(méi)有超過(guò)這個(gè)閾值,如果有,則需要擴(kuò)容。


候選者:鑒于上面的說(shuō)法(HashMap的大小只能是2次冪),所以擴(kuò)容的時(shí)候時(shí)候默認(rèn)是擴(kuò)原來(lái)的2倍

候選者:擴(kuò)容這個(gè)操作肯定是耗時(shí)的,那能不能把負(fù)載因子調(diào)高一點(diǎn),比如我要調(diào)至為1,那我的HashMap就等到16個(gè)元素的時(shí)候才擴(kuò)容呢。

候選者:是可以的,但是不推薦。負(fù)載因子調(diào)高了,這意味著哈希沖突的概率會(huì)增高,哈希沖突概率增高,同樣會(huì)耗時(shí)(因?yàn)椴檎业乃俣茸兟耍?/p>

面試官那我想問(wèn)下,在put元素的時(shí)候,傳遞的Key是怎么算哈希值的?

候選者:實(shí)現(xiàn)就在hash方法上,可以發(fā)現(xiàn)的是,它是先算出正常的哈希值,然后與高16位做異或運(yùn)算,產(chǎn)生最終的哈希值。

候選者:這樣做的好處可以增加了隨機(jī)性,減少了碰撞沖突的可能性。



面試官了解,你簡(jiǎn)單再說(shuō)下put和get方法的實(shí)現(xiàn)吧

候選者:在put的時(shí)候,首先對(duì)key做hash運(yùn)算,計(jì)算出該key所在的index。

候選者:如果沒(méi)碰撞,直接放到數(shù)組中,如果碰撞了,需要判斷目前數(shù)據(jù)結(jié)構(gòu)是鏈表還是紅黑樹(shù),根據(jù)不同的情況來(lái)進(jìn)行插入。

候選者:假設(shè)key是相同的,則替換到原來(lái)的值。最后判斷哈希表是否滿了(當(dāng)前哈希表大小*負(fù)載因子),如果滿了,則擴(kuò)容

候選者:在get的時(shí)候,還是對(duì)key做hash運(yùn)算,計(jì)算出該key所在的index,然后判斷是否有hash沖突

候選者:假設(shè)沒(méi)有沖突直接返回,假設(shè)有沖突則判斷當(dāng)前數(shù)據(jù)結(jié)構(gòu)是鏈表還是紅黑樹(shù),分別從不同的數(shù)據(jù)結(jié)構(gòu)中取出。


面試官那在HashMap中是怎么判斷一個(gè)元素是否相同的呢?

候選者:首先會(huì)比較hash值,隨后會(huì)用==運(yùn)算符和equals()來(lái)判斷該元素是否相同。

候選者:說(shuō)白了就是:如果只有hash值相同,那說(shuō)明該元素哈希沖突了,如果hash值和equals() || == 都相同,那說(shuō)明該元素是同一個(gè)。


面試官你說(shuō)HashMap的數(shù)據(jù)結(jié)構(gòu)是數(shù)組+鏈表/紅黑樹(shù),那什么情況拿下才會(huì)用到紅黑樹(shù)呢?

候選者:當(dāng)數(shù)組的大小大于64且鏈表的大小大于8的時(shí)候才會(huì)將鏈表改為紅黑樹(shù),當(dāng)紅黑樹(shù)大小為6時(shí),會(huì)退化為鏈表。

候選者:這里轉(zhuǎn)紅黑樹(shù)退化為鏈表的操作主要出于查詢和插入時(shí)對(duì)性能的考量。

候選者:鏈表查詢時(shí)間復(fù)雜度O(N),插入時(shí)間復(fù)雜度O(1),紅黑樹(shù)查詢和插入時(shí)間復(fù)雜度O(logN)


面試官你在日常開(kāi)始中LinkedHashMap用的多嗎?

候選者:其實(shí)在日常開(kāi)發(fā)中LinkedHashMap用得不多。

候選者:在前面也提到了,LinkedHashMap底層結(jié)構(gòu)是數(shù)組+鏈表+雙向鏈表,實(shí)際上它繼承了HashMap,在HashMap的基礎(chǔ)上維護(hù)了一個(gè)雙向鏈表。

候選者:有了這個(gè)雙向鏈表,我們的插入可以是有序的,這里的有序不是指大小有序,而是插入有序。

候選者:LinkedHashMap在遍歷的時(shí)候?qū)嶋H用的是雙向鏈表來(lái)遍歷的,所以LinkedHashMap的大小不會(huì)影響到遍歷的性能

面試官那TreeMap呢?

候選者:TreeMap在現(xiàn)實(shí)開(kāi)發(fā)中用得也不多,TreeMap的底層數(shù)據(jù)結(jié)構(gòu)是紅黑樹(shù)

候選者:TreeMap的key不能為null(如果為null,那還怎么排序呢),TreeMap有序是通過(guò)Comparator來(lái)進(jìn)行比較的,如果comparator為null,那么就使用自然順序


面試官再來(lái)講講線程安全的Map吧?HashMap是線程安全的嗎?

候選者:HashMap不是線程安全的,在多線程環(huán)境下,HashMap有可能會(huì)有數(shù)據(jù)丟失和獲取不了最新數(shù)據(jù)的問(wèn)題,比如說(shuō):線程Aput進(jìn)去了,線程Bget不出來(lái)。

候選者:我們想要線程安全,可以使用ConcurrentHashMap

候選者:ConcurrentHashMap是線程安全的Map實(shí)現(xiàn)類,它在juc包下的。

候選者:線程安全的Map實(shí)現(xiàn)類除了ConcurrentHashMap還有一個(gè)叫做Hashtable。

候選者:當(dāng)然了,也可以使用Collections來(lái)包裝出一個(gè)線程安全的Map。

候選者:但無(wú)論是Hashtable還是Collections包裝出來(lái)的都比較低效(因?yàn)槭侵苯釉谕鈱犹譻ynchronize),所以我們一般有線程安全問(wèn)題考量的,都使用ConcurrentHashMap


候選者:ConcurrentHashMap的底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組+鏈表/紅黑樹(shù),它能支持高并發(fā)的訪問(wèn)和更新,是線程安全的。

候選者:ConcurrentHashMap通過(guò)在部分加鎖和利用CAS算法來(lái)實(shí)現(xiàn)同步,在get的時(shí)候沒(méi)有加鎖,Node都用了volatile給修飾。

候選者:在擴(kuò)容時(shí),會(huì)給每個(gè)線程分配對(duì)應(yīng)的區(qū)間,并且為了防止putVal導(dǎo)致數(shù)據(jù)不一致,會(huì)給線程的所負(fù)責(zé)的區(qū)間加鎖

面試官你能給我講講JDK 7 和JDK8中HashMap和ConcurrentHashMap的區(qū)別嗎?

候選者:不能,我不會(huì)

候選者:我在學(xué)習(xí)的時(shí)候也看過(guò)JDK7的HashMap和ConcurrentHashMap,其實(shí)還是有很多不一樣的地方

候選者 比如JDK 7 的HashMap在擴(kuò)容時(shí)是頭插法,在JDK8就變成了尾插法,在JDK7 的HashMap還沒(méi)有引入紅黑樹(shù)….

候選者:ConcurrentHashMap 在JDK7 還是使用分段鎖的方式來(lái)實(shí)現(xiàn),而JDK 8 就又不一樣了。但JDK 7細(xì)節(jié)我大多數(shù)都忘了。

候選者:我就沒(méi)用過(guò)JDK 7的API,我想著現(xiàn)在最低應(yīng)該也是用JDK8了吧?所以我就沒(méi)去仔細(xì)看了。

面試官:你這很危險(xiǎn)!

對(duì)線面試官PDF版本,可+V: java3yyy 免費(fèi)領(lǐng)取

無(wú)語(yǔ)!四年社招還問(wèn)我Java Map集合的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
德清县| 阆中市| 三门峡市| 武威市| 油尖旺区| 刚察县| 井冈山市| 安宁市| 白城市| 吴川市| 白沙| 北辰区| 余干县| 凤城市| 垣曲县| 梨树县| 宜兰县| 香格里拉县| 泌阳县| 七台河市| 中宁县| 巴南区| 明光市| 南康市| 凤翔县| 孝义市| 乐都县| 衡阳市| 达孜县| 平原县| 澄江县| 墨竹工卡县| 墨脱县| 上高县| 辉南县| 通化县| 蓬安县| 康平县| 延川县| 蕲春县| 三穗县|