JDK JDK原始碼分析 LinkedList

2022-05-03 14:15:17 字數 3510 閱讀 2460

概述

相較於 arraylist,linkedlist 在平時使用少一些。

linkedlist 內部是乙個雙向鍊錶,並且實現了 list 介面和 deque 介面,因此它也具有 list 的操作以及雙端佇列和棧的性質。雙向鍊錶的結構如下:

前文分析了 queue 和 deque 介面,正是因為 linkedlist 實現了 deque 介面。linkedlist 的繼承結構如下:

結點類 node

檢視 linkedlist 的原始碼可發現它內部有個巢狀類 node,**如下: 

private

static

class node

}

linkedlist 是雙向鍊錶的實現,而該 node 類則是鍊錶的結點。

此外,linkedlist 還有幾個成員變數如下:

//

list 的長度

transient

int size = 0;

//煉表頭結點

transient nodefirst;

//鍊錶尾結點

transient nodelast;

構造器linkedlist 有兩個構造器,如下:

public

linkedlist()

public linkedlist(collection extends e>c)

ps: 由於鍊錶的容量可以一直增加,因此沒有指定容量的構造器。

其中第乙個為無參構造器;第二個為使用指定的集合構造,並呼叫 addall(),繼續跟進該方法,**如下:

public

boolean addall(collection extends e>c)

public

boolean addall(int index, collection extends e>c)

else

//迴圈將陣列中的元素插入到鍊錶

for(object o : a)

//若插入到末尾,則陣列中的最後乙個元素就是尾結點

if (succ == null

) else

size +=numnew;

modcount++;

return

true

;}

其中 node(index) 方法為獲取指定位置的結點,**如下:

nodenode(int

index)

else

}

該方法通過遍歷鍊錶獲取指定的元素。

值得注意的是,該方法並非直接從頭到尾遍歷整個鍊錶,而是先判斷下標的位置,若在前一半則從前往後遍歷;否則就從後往前遍歷。這樣能減少遍歷結點的個數。

ps: 前文「資料結構與演算法筆記(一)」對鍊錶進行過分析,由於其記憶體空間非連續,因此不支援隨機訪問(下標訪問)。所以,查詢某個結點是通過遍歷整個鍊錶來實現的。

與此同時,get(index) 方法內部也是這樣實現的:

public e get(int

index)

常用方法之前分析 queue 和 deque 的時候提到:queue 中的方法在 deque 中都有對應的。下面簡單分析 linkedlist 中一些常用的方法。

新增結點方法:add(), addlast(), offerlast()

public

boolean

offerlast(e e)

public

void

addlast(e e)

public

boolean

add(e e)

可以看到他們都是呼叫了同乙個方法 linklast(e) 實現的,如下:

void

linklast(e e)

該操作就是將指定的結點新增到鍊錶末尾。

刪除結點方法:poll(), pollfirst(), removefirst()

public

e poll()

public

e pollfirst()

public

e removefirst()

可以看到這三個方法都是呼叫 unlinkfirst() 方法實現的,其**如下:

private e unlinkfirst(nodef)
該方法的操作就是從鍊錶頭部移除乙個結點。

向單鏈表插入和刪除結點的操作示意圖如下(雙鏈錶比這裡多了前驅結點):

棧的入棧(push)和出棧(pop)操作:

public

void

push(e e)

public

e pop()

可以看到這兩個方法直接呼叫了雙端佇列的實現方法。即,該棧是乙個「鏈式棧」。

執行緒安全性

執行緒安全的概念不再贅述。分析以下場景:

若有執行緒 t1 對 linkedlist 進行遍歷,同時執行緒 t2 對其進行結構性修改。

對 linkedlist 的遍歷是通過 listiterator(index) 方法實現的,如下:

public listiteratorlistiterator(int

index)

private

class listitr implements listiterator

public

e next()

public

void

remove()

//...

//是否有其他執行緒對當前物件進行結構修改

final

void

checkforcomodification()

}

該類的 next(), add(e) 等方法在執行時會檢測 modcount 與建立時是否一致(checkforcomodification() 方法),從而判斷是否有其他執行緒對該物件進行了結構修改,若有則丟擲 concurrentmodificationexception 異常。

因此,linkedlist 是執行緒不安全的。

小結

1. linkedlist 內部是「雙向鍊錶」,同時實現了 list 介面和 deque 介面,因此也具備 list、雙端佇列和棧的性質;

2. 執行緒不安全。

stay hungry, stay foolish.

spring原始碼分析 spring原始碼分析

1.spring 執行原理 spring 啟動時讀取應用程式提供的 bean 配置資訊,並在 spring 容器中生成乙份相應的 bean 配置登錄檔,然後根據這張登錄檔例項化 bean,裝配好 bean 之間的依賴關係,為上 層應用提供準備就緒的執行環境。二 spring 原始碼分析 1.1spr...

思科VPP原始碼分析(dpo機制原始碼分析)

vpp的dpo機制跟路由緊密結合在一起。路由表查詢 ip4 lookup 的最後結果是乙個load balance t結構。該結構可以看做是乙個hash表,裡面包含了很多dpo,指向為下一步處理動作。每個dpo都是新增路由時的乙個path的結果。dpo標準型別有 dpo drop,dpo ip nu...

redux原始碼分析(三) 原始碼部分

下面是每個部分的一些解讀 createstore apicreatestore reducer,initialstate enhancer 曾經非常好奇這個函式的第二個引數到底是initialstate還是enhancer,因為見過兩種寫法都有的,以為是版本問題。看了原始碼才發現,都可以的。如果你不...