從源碼出發(fā)帝牡,談?wù)凙rrayList往毡、LinkedList

前言

android 開發(fā)適配器里面存放數(shù)據(jù)用的最多的就是ArrayList,大家有看過ArrayList源碼嗎靶溜,ArrayList的優(yōu)點(diǎn)和確定是什么开瞭,有沒有什么數(shù)據(jù)結(jié)構(gòu)可以替換ArrayList呢?本篇文章帶領(lǐng)大家從源碼角度出發(fā)一起看看ArrayList和LinkedList罩息。

1. ArrayList

ArrayList本質(zhì)是數(shù)組嗤详。它里面的元素都保存在elementdata[] 這樣一個數(shù)組里面

public void add(int index, E element) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

    ensureCapacityInternal(size + 1);  // Increments modCount!! 給ArrayList擴(kuò)容
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}

add的核心代碼是System.arraycopy(elementData, index, elementData, index + 1, size - index);

private static void arraycopy(char[] src, int srcPos, char[] dst, int dstPos, int length) {
    if (src == null) {
        throw new NullPointerException("src == null");
    }
    if (dst == null) {
        throw new NullPointerException("dst == null");
    }
    if (srcPos < 0 || dstPos < 0 || length < 0 ||
        srcPos > src.length - length || dstPos > dst.length - length) {
        throw new ArrayIndexOutOfBoundsException(
            "src.length=" + src.length + " srcPos=" + srcPos +
            " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length);
    }
    if (length <= ARRAYCOPY_SHORT_CHAR_ARRAY_THRESHOLD) {
        // Copy char by char for shorter arrays.
        if (src == dst && srcPos < dstPos && dstPos < srcPos + length) {
            // Copy backward (to avoid overwriting elements before
            // they are copied in case of an overlap on the same
            // array.)
            for (int i = length - 1; i >= 0; --i) {
                dst[dstPos + i] = src[srcPos + i];
            }
        } else {
            // Copy forward.
            for (int i = 0; i < length; ++i) {
                dst[dstPos + i] = src[srcPos + i];
            }
        }
    } else {
        // Call the native version for longer arrays.
        arraycopyCharUnchecked(src, srcPos, dst, dstPos, length);
    }
}

為了方便大家了解,我畫了一個圖


image

所以copy的操作元素就是遍歷元素扣汪,然后進(jìn)行替換操作断楷。
同理,remove()方法也是用了System.copy()方法崭别,只不過是把元素往前挪位置了

掌握了ArrayList方法的原理后我們不難發(fā)現(xiàn)冬筒,如果我們要往ArrayList中添加元素的時候,如果是往最后一個位置添加元素的時候速度是最快的茅主,往中間添加元素舞痰,因為涉及到元素位移操作,所以效率相對較低诀姚。由于arraylist本質(zhì)是數(shù)組响牛,數(shù)組在內(nèi)存中是連續(xù)的空間,所以get(index)是很快的赫段,直接通過elementdata[index]這個數(shù)組就能拿到呀打。

從時間復(fù)雜度來說,ArrayList插入和刪除的時候時間復(fù)雜度為O(n)糯笙,獲取元素的時間復(fù)雜度為O(1)贬丛。

那么有沒有插入和刪除相對較快的數(shù)據(jù)結(jié)構(gòu)呢。

2. LinkedList

LinkedList是一個雙鏈表给涕。

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

    if (index == size)
        linkLast(element);
    else
        linkBefore(element, node(index));
}
void linkBefore(E e, Node<E> succ) {
    // assert succ != null;
    final Node<E> pred = succ.prev;
    final Node<E> newNode = new Node<>(pred, e, succ);
    succ.prev = newNode;
    if (pred == null)
        first = newNode;
    else
        pred.next = newNode;
    size++;
    modCount++;
}

就是把之前的鏈斷開豺憔,前面的元素的尾結(jié)點(diǎn)指向新添加的元素额获,新添加的元素的頭結(jié)點(diǎn)指向前一個元素。后一個元素的頭結(jié)點(diǎn)指向當(dāng)前元素恭应,當(dāng)前元素的尾結(jié)點(diǎn)指向后一個元素抄邀。

同樣的畫個圖方便大家了解
<meta charset="utf-8">


2.png

接下來看下get()方法

public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}

...

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;
    }
}

get()方法最終用for()循環(huán)是輪詢獲取元素,所以效率較低昼榛。

從時間復(fù)雜度來說境肾,LinkedList插入和刪除的時候時間復(fù)雜度為O(1),獲取元素的時間復(fù)雜度為O(n)褒纲。

有沒有一種數(shù)據(jù)結(jié)構(gòu)能夠結(jié)合以上兩個的優(yōu)點(diǎn)呢准夷,下篇文章咱們一起學(xué)習(xí)下HashMap的原理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末莺掠,一起剝皮案震驚了整個濱河市衫嵌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌彻秆,老刑警劉巖楔绞,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異唇兑,居然都是意外死亡酒朵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門扎附,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔫耽,“玉大人,你說我怎么就攤上這事留夜〕渍。” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵碍粥,是天一觀的道長鳖眼。 經(jīng)常有香客問我,道長嚼摩,這世上最難降的妖魔是什么钦讳? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮枕面,結(jié)果婚禮上愿卒,老公的妹妹穿的比我還像新娘。我一直安慰自己潮秘,他們只是感情好掘猿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著唇跨,像睡著了一般稠通。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上买猖,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天改橘,我揣著相機(jī)與錄音,去河邊找鬼玉控。 笑死飞主,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的高诺。 我是一名探鬼主播碌识,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼虱而!你這毒婦竟也來了筏餐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤牡拇,失蹤者是張志新(化名)和其女友劉穎魁瞪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惠呼,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡导俘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了剔蹋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旅薄。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖泣崩,靈堂內(nèi)的尸體忽然破棺而出少梁,到底是詐尸還是另有隱情,我是刑警寧澤律想,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布猎莲,位于F島的核電站,受9級特大地震影響技即,放射性物質(zhì)發(fā)生泄漏著洼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一而叼、第九天 我趴在偏房一處隱蔽的房頂上張望身笤。 院中可真熱鬧,春花似錦葵陵、人聲如沸液荸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娇钱。三九已至伤柄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間文搂,已是汗流浹背适刀。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留煤蹭,地道東北人笔喉。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像硝皂,于是被迫代替她去往敵國和親常挚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355