Java面試崗常見問題之ArrayList和LinkedList的區(qū)別
1.ArrayList和LinkedList是什么?
在我看來,要想搞清楚ArrayList和LinkedList有什么區(qū)別,首先一定得要知道這兩個(gè)東西到底是什么。因?yàn)樵谖铱磥?,通常拿來被比較有區(qū)別的東西,它們大體上一定存在很多相似的地方。為了剖析本質(zhì),我們直接看看它們的源碼聲明。
Arraylist:
LinkedList:
可以看出ArrayList和LinkedList都是List接口下的實(shí)現(xiàn)類,而List接口可以說是集合類中最常用的接口了,它是一個(gè)元素有序、可以重復(fù)、可以為null的集合。而且List接口的元素,都可以直接通過下標(biāo)索引獲取。既然如此,那么說明ArrayList和LinkedList都具有上述的功能,那他們使用起來的效率到底有什么區(qū)別呢?
2.ArrayList和LinkedList性能比較
1.插入效率比較
因?yàn)樯厦嫖覀円呀?jīng)提到過這兩者都是主要用來存儲(chǔ)元素的集合類,那我們可以使用較大的數(shù)據(jù)量,來測(cè)試一下它們插入的效率如何
//插入到頭部 public static void main(String[] args) { ArrayList<Integer> list1 = new ArrayList<>(); LinkedList<Integer> list2 = new LinkedList<>(); long time1 = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { list1.add(0,i); } long time2 = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { list2.add(0,i); } long time3 = System.currentTimeMillis(); //ArrayList的插入時(shí)間 System.out.println(time2-time1);//58746 //LinkedList的插入時(shí)間 System.out.println(time3-time2);//124 }
//插入到尾部 public static void main(String[] args) { ArrayList<Integer> list1 = new ArrayList<>(); LinkedList<Integer> list2 = new LinkedList<>(); long time1 = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { list1.add(i); } long time2 = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { list2.add(i); } long time3 = System.currentTimeMillis(); //ArrayList的插入時(shí)間 System.out.println(time2-time1);//23 //LinkedList的插入時(shí)間 System.out.println(time3-time2);//140 }
大家發(fā)現(xiàn)沒有,當(dāng)插入100萬個(gè)元素到頭部時(shí),LinkedList的速率竟然是ArrayList五千倍之多,當(dāng)我們插入100萬個(gè)元素到尾部時(shí),但是又發(fā)現(xiàn)ArrayList的速率比LinkedList還快,這是為什么呢?
其實(shí)做這個(gè)實(shí)驗(yàn),是為了打消許多人的誤區(qū)——LinkedList的插入效率一定比ArrayList要高。沒錯(cuò),理論上確實(shí)是如此,因?yàn)锳rraylist的底層是數(shù)組實(shí)現(xiàn),而LinkedList的底層為雙向鏈表。在初學(xué)數(shù)據(jù)結(jié)構(gòu)時(shí)鏈表的插入效率高于數(shù)組這是我們就學(xué)習(xí)過的知識(shí),可實(shí)際上在這里其實(shí)當(dāng)數(shù)據(jù)量越來越大時(shí),ArrayList的插入和刪除效率是比LinkedList越來越高的,這涉及到數(shù)組和鏈表在元素操作上的問題。但其實(shí)在元素量較少時(shí),兩者的效率幾乎所差無幾。
2.查詢效率比較
我們向ArrayList和LinkedList同時(shí)插入10萬條數(shù)據(jù),然后去索引每個(gè)下標(biāo),測(cè)試一下兩者的查詢效率如何
public static void main(String[] args) { ArrayList<Integer> list1 = new ArrayList<>(); LinkedList<Integer> list2 = new LinkedList<>(); //先放入一百萬個(gè)元素 for (int i = 0; i < 100000; i++) { list1.add(i); list2.add(i); } long time1 = System.currentTimeMillis(); for (int i = 0; i <list1.size() ; i++) { list1.get(i); } long time2 = System.currentTimeMillis(); for (int i = 0; i <list2.size() ; i++) { list2.get(i); } long time3 = System.currentTimeMillis(); System.out.println(time2-time1);//1 System.out.println(time3-time2);//5479 }
從測(cè)試的結(jié)果來看,并沒有出乎我們的意外,因?yàn)锳rrayList的底層為數(shù)組實(shí)現(xiàn),對(duì)于任何一個(gè)下標(biāo)的索引都是O(1)的時(shí)間復(fù)雜度。而LinkedList的底層為雙向鏈表,對(duì)于查詢索引需要從頭部或者尾部去遍歷找到下標(biāo)。
3.刪除效率比較
我們同樣向ArrayList和LinkedList放入100萬個(gè)元素,然后同樣測(cè)試從頭部刪除和從尾部刪除有什么區(qū)別,來測(cè)試一下他們的刪除效率。
從尾部刪除:
public static void main(String[] args) { ArrayList<Integer> list1 = new ArrayList<>(); LinkedList<Integer> list2 = new LinkedList<>(); //先放入一百萬個(gè)元素 for (int i = 0; i < 1000000; i++) { list1.add(i); list2.add(i); } long time1 = System.currentTimeMillis(); for (int i = 1000000; i >0 ; i--){ list1.remove(i-1); } long time2 = System.currentTimeMillis(); for (int i = 1000000; i >0 ; i--) { list2.remove(i-1); } long time3 = System.currentTimeMillis(); //ArrayList的刪除時(shí)間 System.out.println(time2-time1);//8 //LinkedList的刪除時(shí)間 System.out.println(time3-time2);//18 }
從頭部刪除:
public static void main(String[] args) { ArrayList<Integer> list1 = new ArrayList<>(); LinkedList<Integer> list2 = new LinkedList<>(); //先放入一百萬個(gè)元素 for (int i = 0; i < 1000000; i++) { list1.add(i); list2.add(i); } long time1 = System.currentTimeMillis(); for (int i = 1000000; i >0 ; i--){ list1.remove(0); } long time2 = System.currentTimeMillis(); for (int i = 1000000; i >0 ; i--) { list2.remove(0); } long time3 = System.currentTimeMillis(); System.out.println(time2-time1);//55962 System.out.println(time3-time2);//14 }
大家發(fā)現(xiàn)了嗎,從尾部刪除的時(shí)候,ArrayList的速度比LinkedList快,而從頭部刪除后,ArrayList就不知道被LinkedList甩了幾條街去了。其實(shí)刪除同插入其實(shí)是一樣的,再次實(shí)踐一次是想讓大家加深印象,能走出誤區(qū)。
4.實(shí)驗(yàn)總結(jié)
之所以會(huì)做這幾個(gè)實(shí)驗(yàn),不僅僅是為了讓大家更加深刻的去認(rèn)識(shí)ArrayList和LinkedList,也是想讓大家走出一些誤區(qū),比如什么LinkedList插入刪除一定比ArrayList快啊,ArrayList查詢一定比LinkedList快啊,從理論上來說確實(shí)如此,但通過實(shí)驗(yàn)以后,我們應(yīng)該這樣表達(dá):
1.在數(shù)據(jù)量不大時(shí),ArrayList和LinkedList的查詢效率其實(shí)所差無幾,只有在數(shù)據(jù)量較大時(shí),ArrayList會(huì)對(duì)比出優(yōu)勢(shì)
2.在插入和刪除上,LinkedList并不一定ArrayList效率更好,這與數(shù)據(jù)量以及插入和刪除的位置都是有關(guān)系的
3.面試標(biāo)準(zhǔn)回答
1.ArrayList底層為數(shù)組實(shí)現(xiàn),LinkedList底層為雙向鏈表實(shí)現(xiàn)。ArrayList只能作為列表使用,LinkedList還能作為隊(duì)列,因?yàn)閷?shí)現(xiàn)了Deque接口。
2.LinkedList在數(shù)組中的開銷更大,因?yàn)樗粌H需要存儲(chǔ)元素,還需要保存前后結(jié)點(diǎn)的地址,而ArrayList更加輕量級(jí)。
3. 在插入和刪除效率上,理論上LinkedList優(yōu)于ArrayList,但這還與數(shù)據(jù)量與處理的位置有關(guān)系,但查詢的效率上ArrayList更占有優(yōu)勢(shì)
如果兄弟們?cè)趯?shí)際使用時(shí)實(shí)在糾結(jié)用哪個(gè),那就無腦使用Arraylist吧,別問,問就是它更好用!
到此這篇關(guān)于Java面試崗常見問題之ArrayList和LinkedList的區(qū)別的文章就介紹到這了,更多相關(guān)Java ArrayList和LinkedList的區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java中ArrayList和LinkedList的區(qū)別詳解
- 淺談 java中ArrayList、Vector、LinkedList的區(qū)別聯(lián)系
- 淺析 ArrayList 和 LinkedList 有什么區(qū)別
- ArrayList和LinkedList區(qū)別及使用場(chǎng)景代碼解析
- Java中ArrayList和LinkedList之間的區(qū)別_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- Java ArrayList與LinkedList及HashMap容器的用法區(qū)別
- Java中ArrayList和LinkedList的區(qū)別
- Java中ArrayList和LinkedList區(qū)別
- ArrayList與linkedList的用法區(qū)別及擴(kuò)容方式
- Java中ArrayList和LinkedList有什么區(qū)別舉例詳解
相關(guān)文章
spring事務(wù)Propagation及其實(shí)現(xiàn)原理詳解
這篇文章主要介紹了spring事務(wù)Propagation及其實(shí)現(xiàn)原理詳解,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02SpringBoot生產(chǎn)環(huán)境打包如何去除無用依賴
這篇文章主要介紹了SpringBoot生產(chǎn)環(huán)境打包如何去除無用依賴問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09java實(shí)現(xiàn)web實(shí)時(shí)消息推送的七種方案
這篇文章主要為大家介紹了java實(shí)現(xiàn)web實(shí)時(shí)消息推送的七種方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Springboot使用test無法啟動(dòng)問題的解決
這篇文章主要介紹了Springboot使用test無法啟動(dòng)問題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Spring通過工具類實(shí)現(xiàn)獲取容器中的Bean
在實(shí)際開發(fā)中,我們往往要用到Spring容器為我們提供的諸多資源,例如想要獲取到容器中的配置、獲取到容器中的Bean等等。本文為大家詳細(xì)講講工具類如何獲取到Spring容器中的Bean,需要的可以參考一下2022-06-06Java實(shí)現(xiàn)帶有權(quán)重隨機(jī)算法的示例詳解
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)帶有權(quán)重隨機(jī)算法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10java集合 collection-list-LinkedList詳解
下面小編就為大家?guī)硪黄猨ava集合 collection-list-LinkedList詳解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01Java實(shí)現(xiàn)數(shù)據(jù)脫敏的方法詳細(xì)講解
這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)數(shù)據(jù)脫敏的相關(guān)資料,數(shù)據(jù)脫敏是指對(duì)某些敏感信息通過脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù),需要的朋友可以參考下2023-06-06SpringBoot使用Filter實(shí)現(xiàn)簽名認(rèn)證鑒權(quán)的示例代碼
這篇文章主要介紹了SpringBoot使用Filter實(shí)現(xiàn)簽名認(rèn)證鑒權(quán)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04