《求求大廠給個(gè)Offer》 List面試題
這是三歪的第389篇原創(chuàng)
從今天開始,我,三歪,正式開始寫面試系列。我給這個(gè)面試系列取了一個(gè)名字,叫做《求求大廠給個(gè)Offer》
上一篇就叫做《求求大廠給個(gè)Offer:如何寫簡歷》
所以這篇文章叫做《求求大廠給個(gè)Offer:List面試題》
接下來就開始吧。
這篇文章配套了視頻,感興趣的同學(xué)可以在文末點(diǎn)擊「閱讀原文」觀看,感謝三連和關(guān)注!
面試現(xiàn)場
面試官:“你簡單自我介紹一下吧”
三歪:“我叫三歪,目前維護(hù)一個(gè)公眾號(hào)叫做Java3y,這幾年寫了300+原創(chuàng)技術(shù)文章,近1000頁的原創(chuàng)電子書和多個(gè)知識(shí)點(diǎn)的思維導(dǎo)圖。我的愿景是:只要關(guān)注我并三連的同學(xué)都可以拿到大廠offer。我的....”
面試官:“停停停,別吹了,我們正式開始吧。”
面試官:“來講講Java的List吧,你對(duì)List了解多少?”
三歪:“List在Java里邊是一個(gè)接口,常見的實(shí)現(xiàn)類有ArrayList和LinkedList,在開發(fā)中用得最多的是ArrayList”
面試官:“你再分別來講講ArrayList和LinkedList的區(qū)別唄”
三歪:“ArrayList的底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,LinkedList底層數(shù)據(jù)結(jié)構(gòu)是鏈表。”
面試官:“那我們本身就有數(shù)組了,為什么要用ArrayList呢?”
三歪:“原生的數(shù)組會(huì)有一個(gè)特點(diǎn):你在使用的時(shí)候必須要為它創(chuàng)建大小,而ArrayList不用”
面試官:“那你說說ArrayList是怎么實(shí)現(xiàn)的吧,為什么ArrayList就不用創(chuàng)建大小呢?”
三歪:“其實(shí)是這樣的,我看過源碼。當(dāng)我們new ArrayList()的時(shí)候,默認(rèn)會(huì)有一個(gè)空的Object數(shù)組,大小為0。當(dāng)我們第一次add添加數(shù)據(jù)的時(shí)候,會(huì)給這個(gè)數(shù)組初始化一個(gè)大小,這個(gè)大小默認(rèn)值為10”
面試官:“嗯”
三歪:“還有就是,數(shù)組的大小是固定的,而ArrayList的大小是可變的”
面試官:“那怎么理解固定和可變的呢?你說說看”
三歪:“假設(shè)我們給定數(shù)組的大小是10,要往這個(gè)數(shù)組里邊填充元素,我們只能添加10個(gè)元素。而ArrayList不一樣,ArrayList我們在使用的時(shí)候可以往里邊添加20個(gè),30個(gè),甚至更多的元素”
三歪:“因?yàn)锳rrayList是實(shí)現(xiàn)了動(dòng)態(tài)擴(kuò)容的”
面試官:“那它是怎么實(shí)現(xiàn)的呢?”
三歪:“使用ArrayList在每一次add的時(shí)候,它都會(huì)先去計(jì)算這個(gè)數(shù)組夠不夠空間,如果空間是夠的,那直接追加上去就好了。如果不夠,那就得擴(kuò)容”
面試官:“那怎么擴(kuò)容?一次擴(kuò)多少?”
三歪:“在源碼里邊,有個(gè)grow方法,每一次擴(kuò)原來的1.5倍。比如說,初始化的值是10嘛。現(xiàn)在我第11個(gè)元素要進(jìn)來了,發(fā)現(xiàn)這個(gè)數(shù)組的空間不夠了,所以會(huì)擴(kuò)到15”
三歪:“空間擴(kuò)完容之后,會(huì)調(diào)用arraycopy來對(duì)數(shù)組進(jìn)行拷貝”
面試官:“哦,可以的。那為什么你在前面提到,在日常開發(fā)中用得最多的是ArrayList呢?”
三歪:“是由底層的數(shù)據(jù)結(jié)構(gòu)來決定的,在日常開發(fā)中,遍歷的需求比增刪要多,即便是增刪也是往往在List的尾部添加就OK了。像在尾部添加元素,ArrayList的時(shí)間復(fù)雜度也就O(1)”
三歪:“另外的是,ArrayList的增刪底層調(diào)用的copyOf()被優(yōu)化過,現(xiàn)代CPU對(duì)內(nèi)存可以塊操作,ArrayList的增刪一點(diǎn)兒也不會(huì)比LinkedList慢”
面試官:“Vector你了解嗎?”
三歪:“嗯,Vector是底層結(jié)構(gòu)是數(shù)組,一般現(xiàn)在我們已經(jīng)很少用了。相對(duì)于ArrayList,它是線程安全的,在擴(kuò)容的時(shí)候它是直接擴(kuò)容兩倍的,比如現(xiàn)在有10個(gè)元素,要擴(kuò)容的時(shí)候,就會(huì)將數(shù)組的大小增長到20”
面試官:“嗯,那如果我們不用Vector,線程安全的List還有什么?”
三歪:“首先,我們也可以用Collections來將ArrayList來包裝一下,變成線程安全。但這肯定不是你想聽的,對(duì)吧。在java.util.concurrent包下還有一個(gè)類,叫做CopyOnWriteArrayList”
面試官:“嗯,你繼續(xù)說”
三歪:“要講CopyOnWriteArrayList之前,我還是想說說copy-on-write這個(gè)意思,下面我會(huì)簡稱為cow。比如說在Linux中,我們知道所有的進(jìn)程都是init進(jìn)程fork出來的,除了進(jìn)程號(hào)之外,fork出來的進(jìn)程,默認(rèn)跟父進(jìn)程一模一樣的。在fork之后exec之前,兩個(gè)進(jìn)程用的是相同的內(nèi)存空間的,這意味著子進(jìn)程的代碼段、數(shù)據(jù)段、堆棧都是指向父進(jìn)程的物理空間”
面試官:“嗯”
三歪:“當(dāng)父子進(jìn)程中有更改的行為發(fā)生時(shí),再為子進(jìn)程分配相應(yīng)物理空間。這樣做的好處就是,等到真正發(fā)生修改的時(shí)候,才去分配資源,可以減少分配或者復(fù)制大量資源時(shí)帶來的瞬間延時(shí)。簡單來說,就可以理解為我們的懶加載,或者說單例模式的懶漢式。等真正用到的時(shí)候再分配”
面試官:“嗯”
三歪:“在文件系統(tǒng)中,其實(shí)也有cow的機(jī)制。文件系統(tǒng)的cow就是在修改數(shù)據(jù)的時(shí)候,不會(huì)直接在原來的數(shù)據(jù)位置上進(jìn)行操作,而是重新找個(gè)位置修改。比如說:要修改數(shù)據(jù)塊A的內(nèi)容,先把A讀出來,寫到B塊里面去。如果這時(shí)候斷電了,原來A的內(nèi)容還在。這樣做的好處就是可以保證數(shù)據(jù)的完整性,瞬間掛掉了容易恢復(fù)。
三歪:“再回頭來看CopyOnWriteArrayList吧,CopyOnWriteArrayList是一個(gè)線程安全的List,底層是通過復(fù)制數(shù)組的方式來實(shí)現(xiàn)的。
三歪:“我來說說它 的add()方法的實(shí)現(xiàn)吧”
面試官:“好”
三歪:“在add()方法其實(shí)他會(huì)加lock鎖,然后會(huì)復(fù)制出一個(gè)新的數(shù)組,往新的數(shù)組里邊add真正的元素,最后把a(bǔ)rray的指向改變?yōu)樾碌臄?shù)組”
三歪:“其實(shí)get()方法又或是size()方法只是獲取array所指向的數(shù)組的元素或者大小。讀不加鎖,寫加鎖”
三歪:“可以發(fā)現(xiàn)的是,CopyOnWriteArrayList跟文件系統(tǒng)的COW機(jī)制是很像的”
面試官:“那你能說說CopyOnWriteArrayList有什么缺點(diǎn)嗎?”
三歪:“很顯然,CopyOnWriteArrayList是很耗費(fèi)內(nèi)存的,每次set()/add()都會(huì)復(fù)制一個(gè)數(shù)組出來,另外就是CopyOnWriteArrayList只能保證數(shù)據(jù)的最終一致性,不能保證數(shù)據(jù)的實(shí)時(shí)一致性。假設(shè)兩個(gè)線程,線程A去讀取CopyOnWriteArrayList的數(shù)據(jù),還沒讀完,現(xiàn)在線程B把這個(gè)List給清空了,線程A此時(shí)還是可以把剩余的數(shù)據(jù)給讀出來。”
面試官:“嗯,還可以,今天的面試就到這里結(jié)束了,你有什么想問我的嗎?”
三歪:“你覺得我今天的表現(xiàn)怎么樣?”
面試官:“今天的表現(xiàn)還可以,如果這一次你沒有100個(gè)點(diǎn)贊,估計(jì)HR就不會(huì)再聯(lián)系你了。如果超過100個(gè)點(diǎn)贊,第二輪好好表現(xiàn)吧。”
面試官:“給你透露一下,Map集合可以好好準(zhǔn)備一下,下一輪將會(huì)考察Map的知識(shí)”
題外話
List集合總體來說不會(huì)太難,但CopyOnWriteArrayList可能很多同學(xué)還不知道有這么一個(gè)類。
針對(duì)這次的面試可能你想了解更多List的細(xì)節(jié),比如說ArrayList/LinkedList/CopyOnWriteArrayList的源碼以及上面提到的COW機(jī)制,可以在公眾號(hào)下回復(fù)「List」即可獲取我之前寫的原創(chuàng)文章。
需要預(yù)習(xí)或者領(lǐng)取電子書的同學(xué),在公眾號(hào)下回復(fù)「888」即可獲取。
各類知識(shí)點(diǎn)總結(jié)
下面的文章都有對(duì)應(yīng)的原創(chuàng)精美PDF,在持續(xù)更新中,可以來找我催更~
-
92頁的Mybatis -
129頁的多線程 -
141頁的Servlet -
158頁的JSP -
76頁的集合 -
64頁的JDBC -
105頁的數(shù)據(jù)結(jié)構(gòu)和算法 -
142頁的Spring -
58頁的過濾器和監(jiān)聽器 -
30頁的HTTP -
42頁的SpringMVC -
Hibernate -
AJAX -
Redis -
......
掃碼或者微信搜Java3y 免費(fèi)領(lǐng)取原創(chuàng)思維導(dǎo)圖、精美PDF。在公眾號(hào)回復(fù)「888」領(lǐng)取,PDF內(nèi)容純手打有任何不懂歡迎來問我。
原創(chuàng)電子書
原創(chuàng)思維導(dǎo)圖
![]() |
|




