原始碼閱讀之LinkedList實現細節

2021-09-19 22:02:15 字數 3915 閱讀 9675

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, nodesucc)
這個方法在節點succ前面新增元素,時間複雜度為o(1)。

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

nodenode(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 int indexof(object o)

} else

}return -1;

}

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

peek()

檢視煉表頭節點

public e peek()
peekfirst()

檢視煉表頭節點

public e peekfirst()
peeklast()

檢視鍊錶尾部節點

public e peeklast()
poll()

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

public e poll() 

private e unlinkfirst(nodef)

pollfirst()

同上

public e pollfirst()
polllast()

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

public e polllast() 

private e unlinklast(nodel)

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...