java程序員核心技術(shù)丨List集合源碼分析

ArrayList集合

1.數(shù)據(jù)結(jié)構(gòu)特點

ArrayList底層數(shù)據(jù)結(jié)構(gòu)是一個數(shù)組,查詢元素速度快,增刪速度稍慢

2.幾個概念:

??? (1)DEFAULT_CAPACITY:??? 表示數(shù)組的初始大小,默認(rèn)10

??? (2)size:表示當(dāng)前數(shù)組的大小

??? (3)modCount:統(tǒng)計當(dāng)前數(shù)組元素被修改的次數(shù),只要修改,就+1

3.空參構(gòu)造方法初始化???

public ArrayList() {

??????? //實際大小為{},長度為0的數(shù)組

??????? ??? this.elementData =DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

??? ?}

說明: ArrayList無參構(gòu)造方法初始化時,默認(rèn)大小是空數(shù)組,并不是大家常說的10,10是在第一次add的時候擴(kuò)容的數(shù)組容量值.

4.第一次添加元素擴(kuò)容原理

java

public boolean add(E e) {

??????? //確保數(shù)組大小是否足夠,不夠執(zhí)行擴(kuò)容,size為當(dāng)前數(shù)組的大小

???????ensureCapacityInternal(size + 1);?// Increments modCount!!

??????? //直接把元素e保存到數(shù)組中

???????elementData[size++] = e;

??????? returntrue;

??? }

java

private void ensureCapacityInternal(int minCapacity) {

???ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));

}

private static int calculateCapacity(Object[]elementData, int minCapacity) {

??? //如果是空數(shù)組{}

??? if(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

??????? //在最小容量minCapacity和DEFAULT_CAPACITY(10)選擇一個較大的值

??????? returnMath.max(DEFAULT_CAPACITY, minCapacity);

??? }

??? returnminCapacity;

}

private void ensureExplicitCapacity(int minCapacity) {

??? //記錄修改次數(shù)

??? modCount++;

??? //如果我們期望的最小容量>數(shù)組目前的長度就擴(kuò)容

??? if(minCapacity - elementData.length > 0)

?? ?????grow(minCapacity);

}

private void grow(int minCapacity) {

??? //overflow-conscious code

??? intoldCapacity = elementData.length;

??? //oldCapacity>> 1:是把oldCapacity/2的意思

??? intnewCapacity = oldCapacity + (oldCapacity >> 1);

??? //如果擴(kuò)容后的值<我們期望的值,擴(kuò)容后的值等于我們期望的值

??? if(newCapacity - minCapacity < 0)

???????newCapacity = minCapacity;

??? //如果擴(kuò)容后的值>jvm所能分配的數(shù)組的最大值,那么就用Integer的最大值

??? if(newCapacity - MAX_ARRAY_SIZE > 0)

???????newCapacity = hugeCapacity(minCapacity);

??? //通過復(fù)制數(shù)組擴(kuò)容

??? elementData= Arrays.copyOf(elementData, newCapacity);

}

注意:

??? 1.擴(kuò)容的規(guī)則并不是翻倍,是原來容量大小的1.5倍

??? 2.ArrayList中數(shù)組的最大長度是Integer.MAX_VALUE,超過這個值,JVM就不會給數(shù)組分配內(nèi)存空間了

??? 3.新增元素時,并沒有對值進(jìn)行嚴(yán)格的校驗,所以ArrayList是允許null值的

LinkeList集合

1.數(shù)據(jù)結(jié)構(gòu)特點:

LinkedList底層數(shù)據(jù)結(jié)構(gòu)是一個雙向鏈表,鏈表中的每個節(jié)點都可以查找前一個節(jié)點或者向后查找后一個節(jié)點

2.幾個概念:

(1)鏈表每個節(jié)點叫做Node,Node有prev屬性,代表前一個節(jié)點的地址,next屬性代表后一個節(jié)點的地址

(2)first是雙向鏈表的頭節(jié)點,它的前一個節(jié)點是null

(3)last是雙向鏈表的尾節(jié)點,它的后一個節(jié)點是null

(4)鏈表中如果沒有數(shù)據(jù),first和last都null

(5)因為是雙向鏈表,只要內(nèi)存空間足夠大,鏈表的大小是沒有限制的

3.鏈表中的元素(節(jié)點)叫做Node,是LinkedList集合的私有靜態(tài)內(nèi)部類,代碼如下:

java

private static class Node {

??????? Eitem;//節(jié)點數(shù)據(jù)

???????Node next;//下一個節(jié)點的地址

???????Node prev;//前一個節(jié)點的地址

??????? //初始化參數(shù)順序是: 前一個節(jié)點地址,節(jié)點本身的數(shù)據(jù),后一個節(jié)點地址

???????Node(Node prev, E element, Node next) {

???????????this.item = element;

???????????this.next = next;

???????????this.prev = prev;

??????? }

??? }

4.add添加節(jié)點(從鏈表尾部添加)

java

public boolean add(E e) {

??? linkLast(e);

??? returntrue;//鏈表節(jié)點數(shù)據(jù)可以重復(fù),所以add方法始終返回true

}

java

//從尾部添加節(jié)點

void linkLast(E e) {

??? //把尾節(jié)點地址存儲在l中

??? finalNode l = last;

??? //創(chuàng)建新的節(jié)點,參數(shù)含義如下

??? //l是新節(jié)點的前一個節(jié)點的地址,當(dāng)前值是尾節(jié)點地址值

??? //e是當(dāng)前新增節(jié)點中保存的數(shù)據(jù),當(dāng)前新增節(jié)點的下一個節(jié)點是null,因為是在末尾添加

??? finalNode newNode = new Node<>(l, e, null);

??? //last指向新增節(jié)點(新增節(jié)點作為尾節(jié)點)

??? last =newNode;

??? //如果鏈表為空(第一次添加節(jié)點)(l是尾節(jié)點,尾節(jié)點為空,鏈表即空),頭部和尾部都是指向同一個節(jié)點,都是新建的節(jié)點

??? if (l ==null)

??????? first =newNode;

??? else

??????? //鏈表不是空(非第一次添加節(jié)點),把添加新節(jié)點之前的尾節(jié)點的下一個節(jié)點指向新添加的節(jié)點

??????? l.next =newNode;

??? //節(jié)點數(shù)+1

??? size++;

??? //鏈表的實際修改次數(shù)+1

??? modCount++;

}

5.get(int index)查詢節(jié)點

java

??? public Eget(int index) {

???????checkElementIndex(index);//檢查索引值是否越界

??????? returnnode(index).item;

??? }

??? private voidcheckElementIndex(int index) {

???? ???if (!isElementIndex(index))

???????????throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

??? }

??? privateboolean isElementIndex(int index) {

??????? returnindex >= 0 && index < size;

??? }

??? 核心根據(jù)索引獲取節(jié)點數(shù)據(jù)的方法

??? 鏈表查詢某個節(jié)點是比較慢的,需要挨個查找才可以

java

根據(jù)鏈表索引位置查詢元素

Node node(int index) {

??? //如果index處于鏈表的前半部分,從頭開始查,size>>1 是 size/2的意思

??? if (index< (size >> 1)) {


???????Node x = first;

??????? //知道for循環(huán)到index的前一個node停止

??????? for (inti = 0; i < index; i++)????????????

?????????? ?x = x.next;

??????? returnx;

??? } else {

??????? //如果index處于鏈表的后半部分,從尾開始查

???????Node x = last;

??????? //知道for循環(huán)到index的后一個node停止

??????? for (inti = size - 1; i > index; i--)

??????????? x =x.prev;

??????? returnx;

??? }

}

從源碼中發(fā)現(xiàn),LinkedList并沒有采用從頭循環(huán)到尾的做法,而是采取了簡單二分查找法,

首先看index是在鏈表的左半部分還是右半部分.如果是在左半部分,就從左側(cè)開始找,

如果實在鏈表的有伴部分,就從右側(cè)開始找.這種方式,循環(huán)的次數(shù)至少降低了一半,提高查詢性能.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末匪煌,一起剝皮案震驚了整個濱河市胚迫,隨后出現(xiàn)的幾起案子噪服,更是在濱河造成了極大的恐慌,老刑警劉巖刘离,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異奏赘,居然都是意外死亡寥闪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門磨淌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疲憋,“玉大人,你說我怎么就攤上這事梁只「苛” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵搪锣,是天一觀的道長秋忙。 經(jīng)常有香客問我,道長构舟,這世上最難降的妖魔是什么灰追? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上弹澎,老公的妹妹穿的比我還像新娘朴下。我一直安慰自己,他們只是感情好苦蒿,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布殴胧。 她就那樣靜靜地躺著,像睡著了一般佩迟。 火紅的嫁衣襯著肌膚如雪团滥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天报强,我揣著相機(jī)與錄音灸姊,去河邊找鬼。 笑死躺涝,一個胖子當(dāng)著我的面吹牛厨钻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坚嗜,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼夯膀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了苍蔬?” 一聲冷哼從身側(cè)響起诱建,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碟绑,沒想到半個月后俺猿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡格仲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年押袍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凯肋。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡谊惭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侮东,到底是詐尸還是另有隱情圈盔,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布悄雅,位于F島的核電站驱敲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宽闲。R本人自食惡果不足惜众眨,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一握牧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧娩梨,春花似錦我碟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吱殉。三九已至掸冤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間友雳,已是汗流浹背稿湿。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留押赊,地道東北人饺藤。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像流礁,于是被迫代替她去往敵國和親涕俗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355