ArrayList和LinkedList對(duì)比和插入效率測(cè)試(疑問(wèn))

ArrayList, LinkedList, Vector, Stack是List的4個(gè)實(shí)現(xiàn)類。
ArrayList 是一個(gè)數(shù)組隊(duì)列虽画,相當(dāng)于動(dòng)態(tài)數(shù)組舞蔽。它由數(shù)組實(shí)現(xiàn),隨機(jī)訪問(wèn)效率高码撰,隨機(jī)插入渗柿、隨機(jī)刪除效率低。
LinkedList 是一個(gè)雙向鏈表脖岛。它也可以被當(dāng)作堆棧朵栖、隊(duì)列或雙端隊(duì)列進(jìn)行操作。LinkedList隨機(jī)訪問(wèn)效率低柴梆,但隨機(jī)插入陨溅、隨機(jī)刪除效率低。
Vector 是矢量隊(duì)列绍在,和ArrayList一樣门扇,它也是一個(gè)動(dòng)態(tài)數(shù)組,由數(shù)組實(shí)現(xiàn)偿渡。但是
ArrayList是非線程安全的臼寄,而Vector是線程安全的

Stack 是棧溜宽,它繼承于Vector吉拳。它的特性是:先進(jìn)后出(FILO, First In Last Out)。

(1) 對(duì)于需要快速插入适揉,刪除元素留攒,應(yīng)該使用LinkedList。
(2) 對(duì)于需要快速隨機(jī)訪問(wèn)元素嫉嘀,應(yīng)該使用ArrayList炼邀。
(3) 對(duì)于“單線程環(huán)境” 或者 “多線程環(huán)境,但List僅僅只會(huì)被單個(gè)線程操作”吃沪,此時(shí)應(yīng)該使用非同步的類(如ArrayList)汤善。
對(duì)于“多線程環(huán)境,且List可能同時(shí)被多個(gè)線程操作”票彪,此時(shí)红淡,應(yīng)該使用同步的類(如Vector)。

LinkedList和ArrayList性能差異分析(基于jdk1.8)

1.隨機(jī)插入

LinkedList在指定位置插入元素:

public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }
//查找指定的node
Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

從上面可以看出降铸,通過(guò)add(int,E)向LinkedList中插入元素時(shí)在旱,先是在雙向鏈表中找到要插入節(jié)點(diǎn)的位置index;找到之后推掸,再插入一個(gè)新節(jié)點(diǎn)桶蝎。雙向鏈表查找index位置的節(jié)點(diǎn)時(shí)驻仅,有一個(gè)加速動(dòng)作:若index < 雙向鏈表長(zhǎng)度的1/2,則從前向后查找; 否則登渣,從后向前查噪服。

ArrayList向指定位置插入元素:

public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

可以看到有個(gè)操作

System.arraycopy(elementData, index, elementData, index + 1,
                         size - index)

這意味著,每插入一個(gè)元素胜茧,這個(gè)元素之后的所有元素index都會(huì)改變粘优。之所以插入元素慢,原因就在這里

2.隨機(jī)訪問(wèn)

LinkedList訪問(wèn)指定位置元素

public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
//查找指定的node
Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

可以看出呻顽,在LinkedList中獲取指定元素時(shí)雹顺,需要先在雙向鏈表中找到index位置的元素,然后才能訪問(wèn)
而ArrayList訪問(wèn)指定元素:

public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }
@SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

可以看出廊遍,在ArrayList中獲取指定元素時(shí)嬉愧,直接返回?cái)?shù)組中index位置的元素,而不需要像LinkedList一樣進(jìn)行查找喉前,因此速度更快

3.性能測(cè)試對(duì)比

在頭部插入節(jié)點(diǎn)没酣,元素?cái)?shù)量分別為10000,10 * 10000,100 * 10000, 1000 * 10000, 10000 * 10000,測(cè)試代碼如下:

public static void main(String[] args) {
        
            int[] nums = {10000,10 * 10000,100 * 10000, 1000 * 10000, 10000 * 10000};
            
            for(int i=0; i<nums.length; i++){
                testList(nums[i]);
            }

        
    }
    public static void testList(int num){
        List<String> aList = new ArrayList<String>();
        List<String> lList = new LinkedList<String>();
        long starttime, endtime;
        
        starttime= System.currentTimeMillis();
        for(int i=0; i<num; i++){
            aList.add(0, "1");
        }
        endtime = System.currentTimeMillis();
        System.out.println("num : " + num + "ArrayList cost : " + (endtime - starttime) + "ms");
        
        starttime= System.currentTimeMillis();
        for(int i=0; i<num; i++){
            lList.add(0,"1");
        }
        endtime = System.currentTimeMillis();
        System.out.println("num : " + num + "LinkedList cost : " + (endtime - starttime) + "ms");
    }
}

結(jié)果:

num : 100ArrayList cost : 2ms
num : 100LinkedList cost : 0ms
num : 1000ArrayList cost : 2ms
num : 1000LinkedList cost : 4ms
num : 5000ArrayList cost : 5ms
num : 5000LinkedList cost : 24ms
num : 10000ArrayList cost : 6ms
num : 10000LinkedList cost : 76ms
num : 100000ArrayList cost : 535ms
num : 100000LinkedList cost : 33265ms
num : 1000000ArrayList cost : 84961ms

由于機(jī)子性能一般被饿,卡到100W還在一直跑...
分析:即使在頭部插入節(jié)點(diǎn)四康,LinkedList效率也不如ArrayList,而且性能差很多狭握,和網(wǎng)上資料并不相符。希望有大神可以解釋一下

隨機(jī)插入:

public static void main(String[] args) {
        
            int[] nums = {10000,10 * 10000,100 * 10000, 1000 * 10000, 10000 * 10000};
            
            for(int i=0; i<nums.length; i++){
                testList(nums[i]);
            }

        
    }
    public static void testList(int num){
        List<String> aList = new ArrayList<String>();
        List<String> lList = new LinkedList<String>();
        long starttime, endtime;
        
        starttime= System.currentTimeMillis();
        for(int i=0; i<num; i++){
            aList.add((int)(Math.random()*i), "1");
        }
        endtime = System.currentTimeMillis();
        System.out.println("num : " + num + "ArrayList cost : " + (endtime - starttime) + "ms");
        
        starttime= System.currentTimeMillis();
        for(int i=0; i<num; i++){
            lList.add((int)(Math.random()*i),"1");
        }
        endtime = System.currentTimeMillis();
        System.out.println("num : " + num + "LinkedList cost : " + (endtime - starttime) + "ms");
    }

結(jié)果:

num : 10000ArrayList cost : 12ms
num : 10000LinkedList cost : 87ms
num : 100000ArrayList cost : 477ms
num : 100000LinkedList cost : 37157ms

由于機(jī)子性能一般疯溺,卡到100W還在一直跑...
分析:從上面看出论颅,LinkedList隨機(jī)插入效果還不如ArrayList,感覺(jué)不太對(duì)啊囱嫩,是數(shù)據(jù)量太大了嗎恃疯?那換小一點(diǎn)試試

num : 100ArrayList cost : 2ms
num : 100LinkedList cost : 0ms
num : 1000ArrayList cost : 2ms
num : 1000LinkedList cost : 4ms
num : 5000ArrayList cost : 5ms
num : 5000LinkedList cost : 24ms

效率依然不怎么樣啊,想不明白墨闲。今妄。

在尾部插入:

public static void main(String[] args) {
        
            int[] nums = {10000,10 * 10000,100 * 10000, 1000 * 10000, 10000 * 10000};
            
            for(int i=0; i<nums.length; i++){
                testList(nums[i]);
            }

        
    }
    public static void testList(int num){
        List<String> aList = new ArrayList<String>();
        List<String> lList = new LinkedList<String>();
        long starttime, endtime;
        
        starttime= System.currentTimeMillis();
        for(int i=0; i<num; i++){
            aList.add("1");
        }
        endtime = System.currentTimeMillis();
        System.out.println("num : " + num + "ArrayList cost : " + (endtime - starttime) + "ms");
        
        starttime= System.currentTimeMillis();
        for(int i=0; i<num; i++){
            lList.add("1");
        }
        endtime = System.currentTimeMillis();
        System.out.println("num : " + num + "LinkedList cost : " + (endtime - starttime) + "ms");
    }

結(jié)果:

num : 10000ArrayList cost : 2ms
num : 10000LinkedList cost : 2ms
num : 100000ArrayList cost : 7ms
num : 100000LinkedList cost : 5ms
num : 1000000ArrayList cost : 29ms
num : 1000000LinkedList cost : 22ms
num : 10000000ArrayList cost : 150ms
num : 10000000LinkedList cost : 4874ms
num : 100000000ArrayList cost : 1800ms
num : 100000000LinkedList cost : 66919ms

分析:在數(shù)據(jù)量較小(小于100W)時(shí)鸳碧,兩種list插入效率差不多盾鳞,原因是只在尾部插入,ArrayList并不需要移動(dòng)元素瞻离,而在數(shù)據(jù)量較大時(shí)腾仅,LinkedList效率急速下降,這里我認(rèn)為是LinkedList在插入節(jié)點(diǎn)時(shí)套利,需要向jvm申請(qǐng)空間而導(dǎo)致效率降低推励,在網(wǎng)上也沒(méi)有查到相關(guān)資料

感覺(jué)出現(xiàn)了許多和預(yù)期不一樣的結(jié)果鹤耍,有沒(méi)有大佬可以解釋一下的~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市验辞,隨后出現(xiàn)的幾起案子稿黄,更是在濱河造成了極大的恐慌,老刑警劉巖跌造,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杆怕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鼻听,警方通過(guò)查閱死者的電腦和手機(jī)财著,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)撑碴,“玉大人撑教,你說(shuō)我怎么就攤上這事∽硗兀” “怎么了伟姐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)亿卤。 經(jīng)常有香客問(wèn)我愤兵,道長(zhǎng),這世上最難降的妖魔是什么排吴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任秆乳,我火速辦了婚禮,結(jié)果婚禮上钻哩,老公的妹妹穿的比我還像新娘屹堰。我一直安慰自己,他們只是感情好街氢,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布扯键。 她就那樣靜靜地躺著,像睡著了一般珊肃。 火紅的嫁衣襯著肌膚如雪荣刑。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天伦乔,我揣著相機(jī)與錄音厉亏,去河邊找鬼。 笑死评矩,一個(gè)胖子當(dāng)著我的面吹牛叶堆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斥杜,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼虱颗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沥匈!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起忘渔,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤高帖,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后畦粮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體散址,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年宣赔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了预麸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡儒将,死狀恐怖吏祸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钩蚊,我是刑警寧澤贡翘,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站砰逻,受9級(jí)特大地震影響鸣驱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蝠咆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一踊东、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刚操,春花似錦递胧、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)祝闻。三九已至占卧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間联喘,已是汗流浹背华蜒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留豁遭,地道東北人叭喜。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蓖谢,于是被迫代替她去往敵國(guó)和親捂蕴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子譬涡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 在一個(gè)方法內(nèi)部定義的變量都存儲(chǔ)在棧中,當(dāng)這個(gè)函數(shù)運(yùn)行結(jié)束后啥辨,其對(duì)應(yīng)的棧就會(huì)被回收涡匀,此時(shí),在其方法體中定義的變量將不...
    Y了個(gè)J閱讀 4,413評(píng)論 1 14
  • ? 在編寫(xiě)java程序中溉知,我們最常用的除了八種基本數(shù)據(jù)類型陨瘩,String對(duì)象外還有一個(gè)集合類,在我們的的程序中到處...
    Java幫幫閱讀 1,408評(píng)論 0 6
  • 轉(zhuǎn)自:(http://www.cnblogs.com/Alan-Jones/p/6426994.html) Arr...
    自控力_2018閱讀 873評(píng)論 0 5
  • 下午雷聲響亮级乍,神的憤怒搧在大地上的巴掌響亮 嘲笑這個(gè)蹩腳詩(shī)人挖空心思寫(xiě)無(wú)用的分行堅(jiān)信香樟樹(shù)和酢漿草會(huì)站在他這邊 當(dāng)...
    阿劍啊閱讀 273評(píng)論 0 7
  • 睜開(kāi)雙眼舌劳,天邊露出魚(yú)肚白,才知道這個(gè)夜晚又過(guò)去了玫荣。夢(mèng)中那個(gè)模糊的身影也漸漸消散…… 在這場(chǎng)名為歲月的徒步旅行中甚淡,...
    Mrright_19c6閱讀 326評(píng)論 0 0