從LinkedList的常用方法來解析它的內(nèi)部實現(xiàn)

LinkedList作為一個常用的集合在我們項目開發(fā)當中經(jīng)常會用到愿题,它經(jīng)常會拿來和ArrayList做比較搁宾,那我們今天就通過源碼來解析下它內(nèi)部的實現(xiàn)原理

構(gòu)造方法
 public LinkedList() {
        voidLink = new Link<E>(null, null, null);
        voidLink.previous = voidLink;
        voidLink.next = voidLink;
}

new了一個Link類撕捍,這個Link類包括:添加的數(shù)據(jù)data,鏈表上個對象和下個對象的引用;因為是初始化所以它的數(shù)據(jù)是null,對上一個和下一個的引用也是自己本身健霹。

添加方法
    @Override
    public void add(int location, E object) {
         //如果location大于等于0,并且location小于等于size執(zhí)行下面操作
         // 否則越界異常
        if (location >= 0 && location <= size) {
            Link<E> link = voidLink;
            //如果location小于總大小的1/2,就從鏈表的尾部找
            if (location < (size / 2)) {
                for (int i = 0; i <= location; i++) {
                    link = link.next;
                }
            } else {
                //如果location大于等于總大小的1/2,就從鏈表的頭部找
                for (int i = size; i > location; i--) {
                    link = link.previous;
                }
            }
             
            //插入到location位置
            Link<E> previous = link.previous;
            Link<E> newLink = new Link<E>(object, previous, link);
            previous.next = newLink;
            link.previous = newLink;
            size++;
            modCount++;
        } else {
            throw new IndexOutOfBoundsException();
        }
    }

當我們調(diào)用add(E e)方法的同時瓶蚂,方法內(nèi)部又調(diào)用了add(int location, E object)方法糖埋,location是要添加數(shù)據(jù)的位置,下面我們通過一張圖來看一下它的add機制扬跋。

QQ圖片20170123105921.jpg

如果location是1阶捆,那么就從0開始循環(huán)找,然后把要添加的數(shù)據(jù)添加到0和1之間钦听;
如果location是3洒试,那么就從voidLinked header開始找,然后把數(shù)據(jù)添加到2和3之間朴上。

再來看看其他add方法

    public boolean addAll(Collection<? extends E> collection) {
        int adding = collection.size();
        if (adding == 0) {
            return false;
        }
        Collection<? extends E> elements = (collection == this) ?
                new ArrayList<E>(collection) : collection;

        Link<E> previous = voidLink.previous;
        //下面代碼的邏輯就是:從鏈表的頭開始插入數(shù)據(jù)垒棋,
        // 最后一條數(shù)據(jù)是在鏈表頭上面的數(shù)據(jù)
        for (E e : elements) {
            Link<E> newLink = new Link<E>(e, previous, null);
            previous.next = newLink;
            previous = newLink;
        }
        previous.next = voidLink;
        voidLink.previous = previous;
        size += adding;
        modCount++;
        return true;
    }

addFirst方法

    public void addFirst(E object) {
        addFirstImpl(object);
    }
    
    //把object添加到鏈表的最尾部,因為我們?nèi)?shù)據(jù)的時候是從尾部開始取的
    private boolean addFirstImpl(E object) {
        Link<E> oldFirst = voidLink.next;
        Link<E> newLink = new Link<E>(object, voidLink, oldFirst);
        voidLink.next = newLink;
        oldFirst.previous = newLink;
        size++;
        modCount++;
        return true;
    }

addLast方法

   public void addLast(E object) {
        addLastImpl(object);
    }
   //把object添加到鏈表的頭部
   private boolean addLastImpl(E object) {
        Link<E> oldLast = voidLink.previous;
        Link<E> newLink = new Link<E>(object, oldLast, voidLink);
        voidLink.previous = newLink;
        oldLast.next = newLink;
        size++;
        modCount++;
        return true;
    }
get方法
    @Override
    public E get(int location) {
        if (location >= 0 && location < size) {
            Link<E> link = voidLink;
            if (location < (size / 2)) {
                for (int i = 0; i <= location; i++) {
                    link = link.next;
                }
            } else {
                for (int i = size; i > location; i--) {
                    link = link.previous;
                }
            }
            return link.data;
        }
        throw new IndexOutOfBoundsException();
    }

跟添加數(shù)據(jù)獲取location位置數(shù)據(jù)的邏輯是一致的痪宰,這邊就不細說了叼架。

remove刪除方法
    public E remove(int location) {
        if (location >= 0 && location < size) {
            Link<E> link = voidLink;
            if (location < (size / 2)) {
                for (int i = 0; i <= location; i++) {
                    link = link.next;
                }
            } else {
                for (int i = size; i > location; i--) {
                    link = link.previous;
                }
            }
            //把locaiton位置的對象的上面和下面的對象關(guān)聯(lián)起來
            Link<E> previous = link.previous;
            Link<E> next = link.next;
            previous.next = next;
            next.previous = previous;
            size--;
            modCount++;
            return link.data;
        }
        throw new IndexOutOfBoundsException();
    }

查找數(shù)據(jù)的邏輯和取值的邏輯是一致的,然后就是把location位置對象的上面和下面對象關(guān)聯(lián)起來衣撬。

 @Override
    public boolean remove(Object object) {
        return removeFirstOccurrenceImpl(object);
    }
  //最后調(diào)用了此方法
    private boolean removeOneOccurrence(Object o, Iterator<E> iter) {
        while (iter.hasNext()) {
            E element = iter.next();
            if (o == null ? element == null : o.equals(element)) {
                iter.remove();
                return true;
            }
        }
        return false;
    }

循環(huán)遍歷乖订,通過equals方法對比找到相同的數(shù)據(jù),然后刪除具练。

總結(jié)

LinkedList內(nèi)部存儲數(shù)據(jù)是以鏈表的形式存儲的乍构,查詢數(shù)據(jù)需要從鏈表頭或尾循環(huán)取值,所以會比ArrayList查詢慢扛点,添加和刪除數(shù)據(jù)差不多哥遮,在特定的情況下添加數(shù)據(jù)ArrayList會稍慢,其他方法差別不會特別大陵究。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末眠饮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子铜邮,更是在濱河造成了極大的恐慌仪召,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件松蒜,死亡現(xiàn)場離奇詭異返咱,居然都是意外死亡,警方通過查閱死者的電腦和手機牍鞠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門咖摹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人难述,你說我怎么就攤上這事萤晴。” “怎么了胁后?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵店读,是天一觀的道長。 經(jīng)常有香客問我攀芯,道長屯断,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮殖演,結(jié)果婚禮上氧秘,老公的妹妹穿的比我還像新娘。我一直安慰自己趴久,他們只是感情好丸相,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彼棍,像睡著了一般灭忠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上座硕,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天弛作,我揣著相機與錄音,去河邊找鬼华匾。 笑死映琳,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的瘦真。 我是一名探鬼主播刊头,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼诸尽!你這毒婦竟也來了原杂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤您机,失蹤者是張志新(化名)和其女友劉穎穿肄,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體际看,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡咸产,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了仲闽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脑溢。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖赖欣,靈堂內(nèi)的尸體忽然破棺而出屑彻,到底是詐尸還是另有隱情,我是刑警寧澤顶吮,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布社牲,位于F島的核電站,受9級特大地震影響悴了,放射性物質(zhì)發(fā)生泄漏搏恤。R本人自食惡果不足惜违寿,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望熟空。 院中可真熱鬧藤巢,春花似錦、人聲如沸痛阻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阱当。三九已至,卻和暖如春糜工,著一層夾襖步出監(jiān)牢的瞬間弊添,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工捌木, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留油坝,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓刨裆,卻偏偏與公主長得像澈圈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子帆啃,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

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