原始碼閱讀之LinkedList實現細節

2021-08-31 03:06:38 字數 4411 閱讀 2885

0x00 描述

linkedlist是乙個雙向鍊錶,這是乙個基礎的資料結構。開啟linkedlist原始碼,可以看到它繼承於abstractsequentiallist,這個是abstractlist的子類。同時也實現了listdequecloneserializable介面。所以簡化的類關係圖可以表示為

關鍵屬性

linkedlist是實現了序列化介面serializable,而以上屬性都被宣告為transient表示這些欄位不參與序列化。

節點

private

static

class

node

這個節點類,記錄鍊錶中的節點的資料,有前指標、後指標和具體的資料元素。這個資料這裡用泛型來表示了。

構造方法

public

linkedlist()

這個是預設建構函式,建立乙個空鍊錶。

public

linkedlist

(collection<

?extends

e> c)

這是通過列表來建立鍊錶的。它呼叫了addall方法。這個方法後文會講到。

0x01 常用方法

addfirst(e e)

在鍊錶頭部新增節點

public

void

addfirst

(e e)

private

void

linkfirst

(e e)

它實際是呼叫了內部的乙個私有方法linkfirst。只需要改變指標指向,時間複雜度o(1)。

addlast(e e)

public

void

addlast

(e e)

void

linklast

(e e)

在鍊錶尾部新增乙個節點。它也是內部的linklast方法。這方法執行效率也很高,只需要改變指標指向,時間複雜度是o(1)。

add(e e)

public

boolean

add(e e)

可以看出也是呼叫了linklast方法。

add(int index, e element)

public

void

add(

int index, e element)

private

void

checkpositionindex

(int index)

private

boolean

ispositionindex

(int index)

在某個index前插入元素。

首先它會檢查index是否正確。如果在 0~size 範圍內的下標,那麼就執行插入的方法;

它會判斷如果index是等於size那麼就在尾部插入元素,否則就在index所在節點前面插入元素。

void

linkbefore

(e e, node

succ)

這個方法在節點succ前面新增元素,時間複雜度為o(1)。

在呼叫這個方法之前需要獲取到節點

node

node

(int index)

else

}

在鍊錶中要通過下標查詢乙個節點,需要通過遍歷。這裡做了乙個優化,當index是在前半部分時從鍊錶頭部開始遍歷;如果index超過當前鍊錶的一半時則從後面開始遍歷查詢,它的時間複雜度為o(n)。

addall(collection extends e> c)

public

boolean

addall

(collection<

?extends

e> c)

在尾部插入乙個列表,通過呼叫add(int,collection)來實現。

addall(int index, collection extends e> c)

public

boolean

addall

(int index, collection<

?extends

e> c)

else

//依次把陣列中的節點插入到列表中

for(object o : a)

//鏈結後向指標

if(succ == null)

else

//更新size和modcount

size += numnew;

modcount++

;return

true

;}

這個方法稍微複雜一點

先檢測index是否有效

以陣列的形式獲取到列表資料

找到index所在節點的前向指標,後向指標

依次把陣列中的節點插入到列表中

鏈結後向指標的資料

更新sizemodcount

get(int index)

public e get

(int index)

獲取index所在元素,通過node方法獲取。前面分析可以知道,這個方法需要遍歷,它的時間複雜度是o(n)。

contains(object o)

public

boolean

contains

(object o)

public

intindexof

(object o)

}else

}return-1

;}

查詢某個物件是否存在於該鍊錶中是通過遍歷來實現的。

peek()

檢視煉表頭節點

public e peek()

peekfirst()

檢視煉表頭節點

public e peekfirst()

peeklast()

檢視鍊錶尾部節點

public e peeklast()

poll()

獲取頭節點,並把頭節點從鍊錶中刪除

public e poll()

private e unlinkfirst

(node

f)

pollfirst()

同上

public e pollfirst()

polllast()

獲取尾部節點,並將尾部節點刪除

public e polllast()

private e unlinklast

(node

l)

remove()

刪除頭節點

public e remove()

public e removefirst()

clear()

清空鍊錶

public

void

clear()

first = last = null;

size =0;

modcount++

;}

遍歷整個鍊錶,將節點中的資料置為null

0x02 總結

JDK JDK原始碼分析 LinkedList

概述 相較於 arraylist,linkedlist 在平時使用少一些。linkedlist 內部是乙個雙向鍊錶,並且實現了 list 介面和 deque 介面,因此它也具有 list 的操作以及雙端佇列和棧的性質。雙向鍊錶的結構如下 前文分析了 queue 和 deque 介面,正是因為 lin...

原始碼閱讀 Glide原始碼閱讀之with方法(一)

前言 本篇基於4.8.0版本 原始碼閱讀 glide原始碼閱讀之with方法 一 原始碼閱讀 glide原始碼閱讀之load方法 二 原始碼閱讀 glide原始碼閱讀之into方法 三 大多數情況下,我們使用glide 就一句 但是這一句 裡面蘊含著成噸的 with方法有以下幾個過載方法 publi...

原始碼閱讀 Glide原始碼閱讀之load方法(二)

原始碼閱讀 glide原始碼閱讀之load方法 二 原始碼閱讀 glide原始碼閱讀之into方法 三 首先,load方法有以下幾個過載方法 public requestbuilder load nullable bitmap bitmap public requestbuilder load nu...