LinkList原始碼分析

2021-08-29 04:52:58 字數 3352 閱讀 7543

本篇介紹的linkedlist是list介面的一種實現,它的底層是基於雙向鍊錶實現的,因此它具有插入刪除快而查詢修改慢的特點,此外,通過對雙向鍊錶的操作還可以實現佇列和棧的功能。linkedlist的底層結構如下圖所示。

//結點內部類

private static class node

}

node這個內部類其實很簡單,只有三個成員變數和乙個構造器,item表示結點的值,next為下乙個結點的引用,prev為上乙個結點的引用,通過構造器傳入這三個值。接下來再看看linkedlist的成員變數和構造器。

//集合元素個數

transient int size = 0;

//頭結點引用

transient nodefirst;

//尾節點引用

transient nodelast;

//無參構造器

public linkedlist() {}

//傳入外部集合的構造器

public linkedlist(collection extends e> c)

linkedlist持有頭結點的引用和尾結點的引用,它有兩個構造器,乙個是無參構造器,乙個是傳入外部集合的構造器。與arraylist不同的是linkedlist沒有指定初始大小的構造器。看看它的增刪改查方法。

//增(新增)

public boolean add(e e)

//增(插入)

public void add(int index, e element) else

}//刪(給定下標)

public e remove(int index)

//刪(給定元素)

public boolean remove(object o)

}} else }}

return false;

}//改

public e set(int index, e element)

//查public e get(int index)

linkedlist的新增元素的方法主要是呼叫linklast和linkbefore兩個方法,linklast方法是在鍊錶後面鏈結乙個元素,linkbefore方法是在鍊錶中間插入乙個元素。linkedlist的刪除方法通過呼叫unlink方法將某個元素從鍊錶中移除。下面我們看看鍊錶的插入和刪除操作的核心**。

//鏈結到指定結點之前

void linkbefore(e e, nodesucc) else

//集合元素個數加一

size++;

//修改次數加一

modcount++;

}//解除安裝指定結點

e unlink(nodex) else

//如果給定結點的下乙個結點為空, 說明給定結點為尾結點

if (next == null) else

//將給定結點的元素置空

x.item = null;

//集合元素個數減一

size--;

//修改次數加一

modcount++;

return element;

}

linkbefore和unlink是具有代表性的鏈結結點和解除安裝結點的操作,其他的鏈結和解除安裝兩端結點的方法與此類似,所以我們重點介紹linkbefore和unlink方法。

linkbefore方法的過程圖:

//根據指定位置獲取結點

nodenode(int index)

return x;

} else

return x;}}

通過下標定位時先判斷是在鍊錶的上半部分還是下半部分,如果是在上半部分就從頭開始找起,如果是下半部分就從尾開始找起,因此通過下標的查詢和修改操作的時間複雜度是o(n/2)。通過對雙向鍊錶的操作還可以實現單項佇列,雙向佇列和棧的功能。

單向佇列操作:

//獲取頭結點

public e peek()

//獲取頭結點

public e element()

//彈出頭結點

public e poll()

//移除頭結點

public e remove()

//在佇列尾部新增結點

public boolean offer(e e)

雙向佇列操作:

//在頭部新增

public boolean offerfirst(e e)

//在尾部新增

public boolean offerlast(e e)

//獲取頭結點

public e peekfirst()

//獲取尾結點

public e peeklast()

棧操作:

//入棧

public void push(e e)

//出棧

public e pop()

不管是單向佇列還是雙向佇列還是棧,其實都是對鍊錶的頭結點和尾結點進行操作,它們的實現都是基於addfirst(),addlast(),removefirst(),removelast()這四個方法,它們的操作和linkbefore()和unlink()類似,只不過乙個是對鍊錶兩端操作,乙個是對鍊錶中間操作。可以說這四個方法都是linkbefore()和unlink()方法的特殊情況,因此不難理解它們的內部實現,在此不多做介紹。到這裡,我們對linkedlist的分析也即將結束,對全文中的重點做個總結:

1. linkedlist是基於雙向鍊錶實現的,不論是增刪改查方法還是佇列和棧的實現,都可通過操作結點實現

2. linkedlist無需提前指定容量,因為基於鍊錶操作,集合的容量隨著元素的加入自動增加

3. linkedlist刪除元素後集合占用的記憶體自動縮小,無需像arraylist一樣呼叫trimtosize()方法

4. linkedlist的所有方法沒有進行同步,因此它也不是執行緒安全的,應該避免在多執行緒環境下使用

5. 以上分析基於jdk1.7,其他版本會有些出入,因此不能一概而論

LinkList 部分原始碼導讀

align center img b size large 背景 size b size medium 為了更加好了解linklist的工作原理,上面是鍊錶的示意圖 size private transient entryheader new entry null,null,null private...

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