java-Linkedlist源碼分析

## 深入分析 Java 中的 `LinkedList` 源碼

`LinkedList` 是 Java 集合框架中的一個重要類,它基于雙向鏈表實現,提供了高效的插入和刪除操作。與 `ArrayList` 不同,`LinkedList` 的結構使其在特定操作上有更優的性能表現。本文將詳細分析 `LinkedList` 的源碼,包括其數據結構、構造方法、核心操作等。

### 1. `LinkedList` 的基本數據結構

`LinkedList` 是基于雙向鏈表實現的,這意味著每個節點都包含對前一個節點和后一個節點的引用。`LinkedList` 主要由以下幾個關鍵字段組成:

```java
public class LinkedList<E> extends AbstractSequentialList<E>
? ? ? ? implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
? ? transient int size = 0;
? ? transient Node<E> first;
? ? transient Node<E> last;

? ? private static class Node<E> {
? ? ? ? E item;
? ? ? ? Node<E> next;
? ? ? ? Node<E> prev;

? ? ? ? Node(Node<E> prev, E element, Node<E> next) {
? ? ? ? ? ? this.item = element;
? ? ? ? ? ? this.next = next;
? ? ? ? ? ? this.prev = prev;
? ? ? ? }
? ? }
}
```

- `size`:鏈表中的元素數量。
- `first`:指向鏈表的第一個節點。
- `last`:指向鏈表的最后一個節點。
- `Node`:鏈表節點的內部類,每個節點包含元素數據和前后節點的引用。

### 2. 構造方法

`LinkedList` 提供了多個構造方法:

#### 2.1 默認構造方法

```java
public LinkedList() {
}
```

默認構造方法初始化一個空的鏈表。

#### 2.2 從另一個集合創建 `LinkedList`

```java
public LinkedList(Collection<? extends E> c) {
? ? this();
? ? addAll(c);
}
```

此構造方法從另一個集合創建 `LinkedList`,并將集合中的所有元素添加到鏈表中。

### 3. 核心操作方法

#### 3.1 添加元素

`LinkedList` 提供了多種添加元素的方法:

##### 3.1.1 在鏈表末尾添加元素

```java
public boolean add(E e) {
? ? linkLast(e);
? ? return true;
}

void linkLast(E e) {
? ? final Node<E> l = last;
? ? final Node<E> newNode = new Node<>(l, e, null);
? ? last = newNode;
? ? if (l == null)
? ? ? ? first = newNode;
? ? else
? ? ? ? l.next = newNode;
? ? size++;
? ? modCount++;
}
```

- `add(E e)`:在鏈表末尾添加元素。
- `linkLast(E e)`:將新節點鏈接到鏈表的末尾。如果鏈表為空,則新節點既是 `first` 也是 `last`。

##### 3.1.2 在指定位置插入元素

```java
public void add(int index, E element) {
? ? checkPositionIndex(index);

? ? if (index == size)
? ? ? ? linkLast(element);
? ? else
? ? ? ? linkBefore(element, node(index));
}

void linkBefore(E e, Node<E> succ) {
? ? final Node<E> pred = succ.prev;
? ? final Node<E> newNode = new Node<>(pred, e, succ);
? ? succ.prev = newNode;
? ? if (pred == null)
? ? ? ? first = newNode;
? ? else
? ? ? ? pred.next = newNode;
? ? size++;
? ? modCount++;
}
```

- `add(int index, E element)`:在指定位置插入元素。
- `linkBefore(E e, Node<E> succ)`:在指定節點之前插入新節點。
- `node(int index)`:返回指定位置的節點。

##### 3.1.3 添加元素到鏈表的頭部

```java
public void addFirst(E e) {
? ? linkFirst(e);
}

void linkFirst(E e) {
? ? final Node<E> f = first;
? ? final Node<E> newNode = new Node<>(null, e, f);
? ? first = newNode;
? ? if (f == null)
? ? ? ? last = newNode;
? ? else
? ? ? ? f.prev = newNode;
? ? size++;
? ? modCount++;
}
```

- `addFirst(E e)`:在鏈表頭部添加元素。
- `linkFirst(E e)`:將新節點鏈接到鏈表的頭部。如果鏈表為空,則新節點既是 `first` 也是 `last`。

#### 3.2 刪除元素

`LinkedList` 提供了多種刪除元素的方法:

##### 3.2.1 刪除指定位置的元素

```java
public E remove(int index) {
? ? checkElementIndex(index);
? ? return unlink(node(index));
}

E unlink(Node<E> x) {
? ? final E element = x.item;
? ? final Node<E> next = x.next;
? ? final Node<E> prev = x.prev;

? ? if (prev == null) {
? ? ? ? first = next;
? ? } else {
? ? ? ? prev.next = next;
? ? ? ? x.prev = null;
? ? }

? ? if (next == null) {
? ? ? ? last = prev;
? ? } else {
? ? ? ? next.prev = prev;
? ? ? ? x.next = null;
? ? }

? ? x.item = null;
? ? size--;
? ? modCount++;
? ? return element;
}
```

- `remove(int index)`:刪除指定位置的元素。
- `unlink(Node<E> x)`:斷開指定節點的鏈接,并返回節點中的元素。

##### 3.2.2 刪除鏈表的頭部元素

```java
public E removeFirst() {
? ? final Node<E> f = first;
? ? if (f == null)
? ? ? ? throw new NoSuchElementException();
? ? return unlinkFirst(f);
}

private E unlinkFirst(Node<E> f) {
? ? final E element = f.item;
? ? final Node<E> next = f.next;
? ? f.item = null;
? ? f.next = null; // help GC
? ? first = next;
? ? if (next == null)
? ? ? ? last = null;
? ? else
? ? ? ? next.prev = null;
? ? size--;
? ? modCount++;
? ? return element;
}
```

- `removeFirst()`:刪除鏈表的頭部元素。
- `unlinkFirst(Node<E> f)`:斷開頭部節點的鏈接,并返回節點中的元素。

##### 3.2.3 刪除鏈表的尾部元素

```java
public E removeLast() {
? ? final Node<E> l = last;
? ? if (l == null)
? ? ? ? throw new NoSuchElementException();
? ? return unlinkLast(l);
}

private E unlinkLast(Node<E> l) {
? ? final E element = l.item;
? ? final Node<E> prev = l.prev;
? ? l.item = null;
? ? l.prev = null; // help GC
? ? last = prev;
? ? if (prev == null)
? ? ? ? first = null;
? ? else
? ? ? ? prev.next = null;
? ? size--;
? ? modCount++;
? ? return element;
}
```

- `removeLast()`:刪除鏈表的尾部元素。
- `unlinkLast(Node<E> l)`:斷開尾部節點的鏈接,并返回節點中的元素。

#### 3.3 獲取元素和修改元素

`LinkedList` 提供了獲取和修改元素的方法:

##### 3.3.1 獲取元素

```java
public E get(int index) {
? ? checkElementIndex(index);
? ? return node(index).item;
}

Node<E> node(int index) {
? ? if (index < (size >> 1)) {
? ? ? ? Node<E> x = first;
? ? ? ? for (int i = 0; i < index; i++)
? ? ? ? ? ? x = x.next;
? ? ? ? return x;
? ? } else {
? ? ? ? Node<E> x = last;
? ? ? ? for (int i = size - 1; i > index; i--)
? ? ? ? ? ? x = x.prev;
? ? ? ? return x;
? ? }
}
```

- `get(int index)`:根據索引獲取元素。
- `node(int index)`:返回指定位置的節點,通過判斷索引位置決定從前往后還是從后往前遍歷,提高效率。

##### 3.3.2 修改元素

```java
public E set(int index, E element) {
? ? checkElementIndex(index);
? ? Node<E> x = node(index);
? ? E oldVal = x.item;
? ? x.item = element;
? ? return oldVal;
}
```

- `set(int index, E element)`:根據索引修改元素,并返回舊元素。

### 4. 雙向鏈表的結構特點

#### 4.1 鏈表節點的定義

在 `LinkedList` 中,每個節點包含一個元素和對前后節點的引用:

```java
private static class Node<E> {
? ? E item;
? ? Node<E> next;
? ? Node<E> prev;

? ? Node(Node<E> prev, E element, Node<E> next) {
? ? ? ? this.item = element;
? ? ? ? this.next = next;
? ? ? ? this.prev = prev;
? ? }
}
```

- `item`:存儲節點的元素。
- `next`:指向下一個節點。
- `prev`:指向前一個節點。

#### 4.2 鏈表的首尾節點

`LinkedList` 通過 `first` 和 `last` 字段分別指向鏈表的首節點和尾節點,這樣可以高效地進行頭部和尾部的插入和刪除操作。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/41279.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41279.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/41279.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

android 進程,線程調度的區別

一 分析&#xff1a; 進程和線程在調度上有什么不同呢&#xff1f;當有一個task去占用指定的資源時候叫進程&#xff0c;當有多個task去共享使用這些資源時候&#xff0c;這個task和之后的task都叫線程&#xff08;最初這個task叫主線程&#xff09;而linux調度主要調的就是cp…

【Portswigger 學院】文件上傳

教程和靶場來源于 Burpsuite 的官網 Portswigger&#xff1a;File upload vulnerabilities - PortSwigger 原理與危害 很多網站都有文件上傳的功能&#xff0c;比如在個人信息頁面允許用戶上傳圖片作為頭像。如果網站應用程序對用戶上傳的文件沒有針對文件名、文件類型、文件內…

前端基礎:JavaScript(篇一)

目錄 JavaScript概述 JavaScript歷史&#xff1a; 須知&#xff1a; 基本語法 變量 代碼 運行 數據類型 1、數值型(number)&#xff1a; 代碼 運行 2、布爾型(boolean)&#xff1a; 代碼 運行 3、字符串型&#xff1a; 代碼 運行 4、 undefined類型 代碼…

TCP的pop網絡模式

TCP的pop網絡模式 1、tcp連接的狀態有以下11種 CLOSED&#xff1a;關閉狀態LISTEN&#xff1a;服務端狀態&#xff0c;等待客戶端發起連接請求SYN_SENT&#xff1a;客戶端已發送同步連接請求&#xff0c;等待服務端相應SYN_RECEIVED&#xff1a;服務器收到客戶端的SYN請請求&…

MySQL 基本語法講解及示例(下)

第六節&#xff1a;如何檢索資料 在本節中&#xff0c;我們將介紹如何使用SQL語句檢索數據庫中的資料&#xff0c;具體包括選擇特定列、排序、條件過濾以及組合排序等操作。我們以一個名為student的表格為例&#xff0c;演示不同的檢索方法。 初始表格 student student_idname…

修復harbor的/account/sign-in\?globalSearch=b不登錄可以查詢鏡像的問題

Nginx的location指令不能直接匹配查詢參數&#xff0c;所以需要通過其他方式來處理。這里是一個使用if指令結合查詢參數來實現的方法。該方法會在請求路徑中帶有特定查詢參數時返回404。 使用if指令匹配查詢參數 打開Nginx配置文件&#xff1a; sudo vim /etc/nginx/sites-ava…

Python中frozenset,秒變不可變集合,再也不用擔心多線程了!

目錄 1、Frozenset基礎介紹 ?? 1.1 Frozenset定義與創建 1.2 不可變集合特性 1.3 與Set的區別對比 2、Frozenset操作實踐 ?? 2.1 初始化與添加元素嘗試 2.2 成員測試: in & not in 2.3 集合運算: 并集、交集、差集 2.4 使用場景示例: 字典鍵、函數參數默認值 …

登錄設計(實戰項目)-1個手機號多用戶身份登錄

一. 背景&#xff1a; 該需求是一個互聯網醫院的預約單場景&#xff0c;護士在小程序上申請患者查房預約單&#xff0c;醫生在小程序上對預約單進行接單&#xff0c;護士開始查房后填寫查房小結&#xff0c;客戶需要對用戶信息進行授權&#xff0c;醫生查房后進行簽字&#xff…

勁爆!華為享界兩款新車曝光,等等黨有福了

文 | AUTO芯球 作者 | 雷慢 勁爆啊&#xff0c;北汽的一份環境影響分析報告&#xff0c; 不僅曝光了享界S9的生產進展&#xff0c; 還泄露了自家的另兩款產品&#xff0c; 第一款是和享界S9同尺寸的旅行車&#xff0c; 我一看&#xff0c;這不是我最喜歡的“瓦罐”嗎&…

v-html 空格/換行不生效

接口返回的內容如下&#xff1a;有空格有換行&#xff0c;但 使用v-html無效 需加css樣式 white-space: pre-wrap; <div class"pretty-html" v-html"Value"></div>.pretty-html {white-space: pre-wrap; /* 保留空格和換行&#xff0c;并允許…

掌握麥肯錫精英的6個技巧,你也能成為1%的精英!

不知道大家有沒有想過&#xff0c;我們和那些全球頂尖精英的差距可能只有1%&#xff0c;只是99%的人還不知道這件事。 今天給大家推薦一本好書&#xff0c;《你和麥肯錫精英的差別只有1%》。優思學院發現&#xff0c;在我們的六西格瑪、精益管理的學生中很多人對自己沒有自信。…

軟通動力子公司鴻湖萬聯最新成果SwanLink AI亮相世界人工智能大會

7月4日&#xff0c;2024世界人工智能大會暨人工智能全球治理高級別會議&#xff08;WAIC 2024&#xff09;在上海拉開帷幕&#xff0c;軟通動力董事長兼首席執行官劉天文受邀出席開幕式。其間&#xff0c;軟通動力攜子公司鴻湖萬聯深度參與到大會各項活動中&#xff0c;并全面展…

C語言_結構體初階(還未寫完)

結構體的聲明 1. 什么是結構&#xff1f;結構是一些值的集合&#xff0c;這些值稱為成員變量。結構的每個成員可以是不同類型的變量 數組&#xff1a;一組相同類型元素的集合 結構體&#xff1a;一組不一定相同類型元素的集 2. 結構的聲明 struct tag //tag根據實際情況給名字…

Spring注解@Qualifier

Autowired 注解是 Spring 依賴注入。但是有些場景下僅僅靠這個注解不足以讓Spring知道到底要注入哪個 bean。 默認情況下&#xff0c;Autowired 按類型裝配 Spring Bean。 如果容器中有多個相同類型的 bean&#xff0c;則框架將拋出 NoUniqueBeanDefinitionException&#xff0…

數字化產科管理平臺全套源碼,java產科電子病歷系統源碼

數字化產科管理平臺全套成品源碼&#xff0c;產科電子病歷系統源碼&#xff0c;多家大型婦幼專科醫院應用案例。源碼完全授權交付。 數字化產科管理平臺&#xff08;智慧產科系統&#xff09;是為醫院產科量身定制的信息管理系統。它管理了孕婦從懷孕開始到生產結束42天以內的一…

數據庫MySQL學習筆記

數據庫MySQL學習筆記 主要記錄常見的MySQL語句學習過程&#xff0c;增刪改查。 -- 顯示所有數據庫 SHOW DATABASES;-- 創建新數據庫 CREATE DATABASE mydatabase;-- 使用數據庫 USE mydatabase;-- 顯示當前數據庫中的所有表 SHOW TABLES;-- 創建新表 CREATE TABLE users (id …

BERT--學習

一、Transformer Transformer&#xff0c;是由編碼塊和解碼塊兩部分組成&#xff0c;其中編碼塊由多個編碼器組成&#xff0c;解碼塊同樣也是由多個解碼塊組成。 編碼器&#xff1a;自注意力 全連接 多頭自注意力&#xff1a;Q、K、V 公式&#xff1a; 解碼塊&#xff1…

【Hive實戰】 HiveMetaStore的指標分析

HiveMetaStore的指標分析&#xff08;一&#xff09; 文章目錄 HiveMetaStore的指標分析&#xff08;一&#xff09;背景目標部署架構 hive-site.xml相關配置元數據服務的指標相關配置 源碼部分&#xff08;hive2.3系&#xff09;JvmPauseMonitor.javaHiveMetaStore的內部類HMS…

【anaconda】—“conda info“命令后conda配置和環境信息的理解

文章目錄 conda配置和環境信息的理解 conda配置和環境信息的理解 安裝anaconda成功后&#xff0c;打開cmd&#xff0c;輸入"conda info"命令&#xff0c;結果顯示如下&#xff1a; conda的配置和環境信息的輸出。以下是對每個字段的解釋&#xff1a; active environm…

H2 Database Console未授權訪問漏洞封堵

背景 H2 Database Console未授權訪問&#xff0c;默認情況下自動創建不存在的數據庫&#xff0c;從而導致未授權訪問。各種未授權訪問的教程&#xff0c;但是它怎么封堵呢&#xff1f; -ifExists 很簡單&#xff0c;啟動參數添加 -ifExists &#xff0c;它的含義&#xff1a…