第三章 LinkedList原始碼分析

2021-09-24 17:07:06 字數 4560 閱讀 8090

linkedlist底層是乙個雙向鍊錶,是乙個直線型的鍊錶結構(在jdk1.7以前,其底層是雙向迴圈鍊錶)。

1.建立

//鍊錶中的所儲存的元素個數

transient int size = 0;

//指向頭結點的指標

transient nodefirst;

//指向尾結點的指標

transient nodelast;

//無參建構函式

public linkedlist()

/*** 將乙個集合作為引數初始化列表

* 先呼叫無參建構函式

* 然後呼叫addall(c)方法。

*/public linkedlist(collection<? extends e> c)

/*** 通過呼叫addall(int index, collection<? extends e> c) 完成集合的新增。

* 下面會具體介紹該方法。

*/public boolean addall(collection<? extends e> c)

2.節點node構造

private static class node

}

node 類是linkedlist中的私有內部類,linkedlist中就是通過node來儲存集合中的元素。

3.新增元素

3.1 addall(collection<? extends e> c)

//addall ,在尾部批量增加

public boolean addall(collection<? extends e> c)

//以index為插入下標,插入集合c中所有元素

public boolean addall(int index, collection<? extends e> c) else

//鍊錶批量增加,是靠for迴圈遍歷原陣列,依次執行插入節點操作。對比arraylist是通過system.arraycopy完成批量增加的

for (object o : a)

last = pred; //則設定尾節點

} else

size += numnew; // 修改數量size

modcount++; //修改modcount

return true;

}//根據index 查詢出node,

nodenode(int index) else

}private void checkpositionindex(int index)

private boolean ispositionindex(int index)

小結:

2.2 插入單個節點 add(e)

在尾部插入新的節點

//在尾部插入乙個節點: add

public boolean add(e e)

//生成新節點 並插入到 鍊錶尾部, 更新 last/first 節點。

void linklast(e e)

在指定位置插入新的節點

//在指定下標,index處,插入乙個節點

public void add(int index, e element)

//在succ節點前,插入乙個新節點e

void linkbefore(e e, nodesucc)

4.刪除節點

刪除指定位置的節點

//刪:remove目標節點

public e remove(int index)

//從鍊錶上刪除x節點

e unlink(nodex) else

if (next == null) else

x.item = null; //將當前元素值置空

size--; //修改數量

modcount++; //修改modcount

return element; //返回取出的元素值

} private void checkelementindex(int index)

//下標[0,size)

private boolean iselementindex(int index)

刪除指定元素的節點

//因為要考慮 null元素,也是分情況遍歷

public boolean remove(object o)

}} else }}

return false;

}//將節點x,從鍊錶中刪除

e unlink(nodex) else

//如果後置節點為null,說明是尾節點

if (next == null) else

//將刪除節點的元素值置null,以便gc

x.item = null;

size--;//修改size

modcount++;//修改modcount

return element;//返回刪除的元素值

}

5.修改節點

public e set(int index, e element)
6.查詢節點

根據下標查詢節點

public e get(int index) 

//先判斷指定下標是在鍊錶的前半部分還是後半部分,然後選擇從前遍歷或者從後遍歷

//使用位運算來進行判斷

nodenode(int index) else

}

根據節點物件查詢下標

public int indexof(object o) 

} else

}return -1;

}

7.toarray()

public object toarray()
8.包含contains(o)

判斷linkedlist是否包含某乙個元素。 

底層通過呼叫indexof()。該方法主要用於計算元素在linkedlist中的位置。 

其實indexof()方法也非常簡單: 

首先依據obejct是否為空,分為兩種情況: 

然後通過在每種情況下,從頭節點開始遍歷linkedlist,判斷是否有與object相等的元素,如果有,則返回對應的位置index,如果找不到,則返回-1。

public boolean contains(object o) 

public int indexof(object o)

} else

}return -1;

}

9.操作頭結點、尾結點的方法

//在頭結點新增乙個元素

public void addfirst(e e)

//在尾結點新增乙個元素

public void addlast(e e)

/*** 私有方法,新增頭結點

*/private void linkfirst(e e)

/***私有方法,新增尾結點

*/void linklast(e e)

//刪除頭結點

public e removefirst()

//刪除尾結點

public e removelast()

/*** 刪除非空頭結點

*/private e unlinkfirst(nodef)

/*** 刪除非空尾結點

*/private e unlinklast(nodel)

//獲取頭結點的值

public e getfirst()

//獲取尾結點的值

public e getlast()

在jdk1.7之前,linkedlist的底層結構是乙個雙向迴圈鍊錶,必定擁有乙個header節點,自1.7版本開始,其底層結構變為雙向鍊錶,為了實現快速的找到最後乙個結點以及從後往前遍歷鍊錶,jdk開發人員直接宣告了first和last兩個結點型別的引用這樣既可以在鍊錶頭部插入結點,也可以在結點尾部插入結點。並且可以快速的拿到頭部結點和尾部結點(first和last引用)。

10.清空linkedlist中的所有元素

public void clear() 

first = last = null;

size = 0;

modcount++;

}

linkedlist 是雙向鍊錶。

參考文章:張旭童  面試必備:linkedlist原始碼解析(jdk8)

lframe  linkedlist原始碼解析(基於jdk1.8)

第三章 堆疊

1.基礎知識 堆疊可以實現很多的應用,遞迴的問題轉化成非遞迴形式,在本質上也是堆疊的問題.它是一種 filo 操作的資料結構,一般也有兩種儲存方式 陣列跟鍊錶實現形式,這裡我給出了鍊錶形式的堆疊模板,裡面包括了基本的堆疊所有的操作,還有兩個比較著名的應用例子,時間倉促,精力比較有限,關於迷宮老鼠還沒...

第三章 曙光

第三章 曙光 第二場校園招聘開始了。其實,洋對這個公司的不是很了解。因為前幾天突然在bbs上面看到了這個公司的招聘資訊,洋覺得這個公司不錯,就上網投了簡歷。接下來的乙個多小時,讓洋很震撼!想不到這個公司這個厲害,而且無論從哪方面來說,絕對不比之前的那個公司差。想不到自己的乙個不經意的決定到了這個大的...

第三章 遞迴

遞迴是一種強大的方法,它允許乙個物件以其自身更小的形式來定義自己。恐怕沒有什麼比觀察神秘的自然界中出現的遞迴現象更好的方法來體會遞迴的重要意義了。想想蕨類植物的葉子,每片葉子的小枝幹都是整片葉子的較小縮影 又或者兩個反光的物體,相互對映對方的漸遠的影像。這樣的例子使我們明白儘管大自然的力量是強大的,...