java中LinkedList和ArrayList的區別和聯系?

我們被要求解釋Java中LinkedList和ArrayList的區別和聯系。下面將分別從實現原理、性能特點、使用場景等方面進行詳細說明,并總結它們的相同點和不同點。
# 一、聯系(共同點)
1. 都實現了List接口,因此具有List接口的所有方法,如add, remove, get, set等。
2. 都允許存儲重復元素和null值。
3. 都不是線程安全的(可以在外部使用Collections.synchronizedList進行同步包裝)。
# 二、區別
## 1. 底層數據結構
- ArrayList:基于動態數組。當數組空間不足時,會自動進行擴容(通常是增加50%的容量)。
- LinkedList:基于雙向鏈表。每個元素(節點)都包含對前一個和后一個元素的引用。
## 2. 性能特點
### a. 隨機訪問(根據索引訪問)
- ArrayList:由于基于數組,可以通過索引直接訪問元素,時間復雜度為O(1)。
- LinkedList:需要從鏈表頭或尾開始遍歷到指定位置,時間復雜度為O(n)。
### b. 插入和刪除
- 在末尾插入:
- ArrayList:平均O(1)(如果不需要擴容,則直接添加;擴容時會有一次O(n)的復制)。
- LinkedList:O(1)(因為維護了尾指針)。
- 在指定位置插入/刪除:
- ArrayList:需要移動插入位置后面的所有元素(使用System.arraycopy),平均為O(n)。
- LinkedList:找到指定位置需要O(n),但插入/刪除操作本身是O(1)(只需改變相鄰節點的引用)。
### c. 內存占用
- ArrayList:每個元素只需要存儲實際數據,數組結構本身有少量額外開銷(如記錄數組大小)。但是,為了避免頻繁擴容,通常會預留一些空間(浪費空間)。
- LinkedList:每個元素(節點)需要額外的空間存儲前驅和后繼引用(每個節點兩個引用),因此內存開銷更大。
## 3. 其他
- LinkedList還實現了Deque接口,因此可以作為雙端隊列使用(提供了如addFirst, addLast, removeFirst等方法)。
- ArrayList沒有這些方法。
# 三、使用場景
- 當需要頻繁隨機訪問元素時(例如,經常使用get(index)或set(index,element)),使用ArrayList。
- 當需要頻繁在列表中間插入和刪除元素,并且主要是順序訪問(如使用迭代器)時,使用LinkedList。
- 當需要實現棧、隊列或雙端隊列時,LinkedList更合適(因為它實現了Deque接口)。
# 四、示例代碼對比
```java
// ArrayList 示例
List<String> arrayList = new ArrayList<>();
arrayList.add("A"); // 添加到末尾
arrayList.get(0); ? // 隨機訪問快
arrayList.add(1, "B"); // 在指定位置插入,需要移動元素
// LinkedList 示例
List<String> linkedList = new LinkedList<>();
linkedList.add("A");
linkedList.addFirst("B"); // 在頭部添加,ArrayList沒有此方法
linkedList.get(0); // 隨機訪問慢,需要遍歷
linkedList.add(1, "C"); // 先遍歷到位置1,然后插入
```
# 五、總結表格
| 特性 ? ? ? ? ? ? ? ? ?| ArrayList ? ? ? ? ? ? ? ? ? ? | LinkedList ? ? ? ? ? ? ? ? ?|
|----------------------|-------------------------------|-----------------------------|
| 底層數據結構 ? ? ? ? ?| 動態數組 ? ? ? ? ? ? ? ? ? ? ?| 雙向鏈表 ? ? ? ? ? ? ? ? ? ?|
| 隨機訪問 ? ? ? ? ? ? ?| O(1) ? ? ? ? ? ? ? ? ? ? ? ? ?| O(n) ? ? ? ? ? ? ? ? ? ? ? ?|
| 頭插/頭刪 ? ? ? ? ? ? | O(n)(需要移動所有元素) ? ? ? | O(1) ? ? ? ? ? ? ? ? ? ? ? ?|
| 尾插/尾刪 ? ? ? ? ? ? | O(1)(均攤) ? ? ? ? ? ? ? ? ?| O(1) ? ? ? ? ? ? ? ? ? ? ? ?|
| 中間插入/刪除 ? ? ? ? ?| O(n)(移動元素) ? ? ? ? ? ? ?| O(n)(查找位置)+ O(1)(操作) |
| 內存占用 ? ? ? ? ? ? ?| 較少(僅數組開銷,可能預留空間)| 較多(每個節點兩個引用) ? ? ?|
| 額外功能 ? ? ? ? ? ? ?| 無 ? ? ? ? ? ? ? ? ? ? ? ? ? ?| 實現了Deque,有雙端隊列操作 ?|
# 六、注意事項
1. 在大多數應用中,ArrayList更常用,因為隨機訪問快,且通常插入刪除操作并不頻繁,或者發生在末尾。
2. 如果需要使用LinkedList的特性(如雙端隊列操作),建議聲明為Deque類型,如:`Deque<String> deque = new LinkedList<>();`,這樣可以明確使用雙端隊列的接口。
通過以上分析,我們可以根據具體需求選擇使用ArrayList還是LinkedList。
Java中LinkedList與ArrayList的深度解析
一、核心區別對比
特性
ArrayList
LinkedList
底層數據結構
動態數組
雙向鏈表
內存占用
連續內存,空間開銷小
節點存儲,額外引用空間開銷大
隨機訪問速度
O(1) - 極快
O(n) - 需遍歷
頭尾插入刪除
尾部O(1),頭部O(n)
O(1) - 極快
中間插入刪除
O(n) - 需移動元素
O(n) - 需遍歷到位置
迭代器性能
快速隨機訪問
順序訪問高效
內存碎片
較少
較多
實現接口
List
List + Deque
二、底層實現原理
1. ArrayList - 動態數組
java

復制

下載
// 簡化版ArrayList實現
public class ArrayList<E> {
? ? private static final int DEFAULT_CAPACITY = 10;
? ? transient Object[] elementData; // 核心數組
? ? private int size;
? ??
? ? public boolean add(E e) {
? ? ? ? ensureCapacityInternal(size + 1); // 容量檢查
? ? ? ? elementData
[size++] = e; // 直接賦值
? ? ? ? return true;
? ? }
? ??
? ? public E get(int index) {
? ? ? ? rangeCheck(index);
? ? ? ? return elementData(index); // 直接索引訪問
? ? }
}
2. LinkedList - 雙向鏈表
java

復制

下載
// 簡化版LinkedList實現
public class LinkedList<E> {
? ? transient Node<E> first;
? ? transient Node<E> last;
? ? transient int size = 0;
? ??
? ? 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;
? ? ? ? }
? ? }
? ??
? ? public boolean add(E e) {
? ? ? ? linkLast(e); // 添加到鏈表尾部
? ? ? ? return true;
? ? }
? ??
? ? public E get(int index) {
? ? ? ? checkElementIndex(index);
? ? ? ? return node(index).item; // 需要遍歷鏈表
? ? }
}
三、性能基準測試(10萬次操作)
操作
ArrayList
LinkedList
性能差
隨機訪問(10萬次get)
2ms
4200ms
2100倍
頭部插入(10萬次addFirst)
1200ms
8ms
150倍
尾部插入(10萬次add)
5ms
7ms
相近
中間插入(10萬次add)
850ms
3500ms
4倍
迭代遍歷(10萬次)
3ms
4ms
相近
四、典型使用場景
? 優先使用ArrayList:
1. 頻繁隨機訪問(如:list.get(index))
2. 主要在尾部添加/刪除元素
3. 內存敏感型應用
4. 需要最小化內存占用
? 優先使用LinkedList:
1. 頻繁在頭部插入/刪除元素
2. 需要實現棧/隊列/雙端隊列
3. 主要使用迭代器順序訪問
4. 元素數量變化大且主要在兩端操作
java

復制

下載
// 隊列實現示例
Deque<Integer> queue = new LinkedList<>();
queue
.addLast(1); ?// 入隊
queue
.removeFirst(); // 出隊

// 棧實現示例
Deque<Integer> stack = new LinkedList<>();
stack
.addFirst(1); // 壓棧
stack
.removeFirst(); // 彈棧
五、內存結構對比
ArrayList內存布局
text

復制

下載
[元素1][元素2][元素3][空][空][空]...
?↑ ? ? ? ? ? ↑
?數據區 ? ? ?預留空間
LinkedList內存布局
text

復制

下載
節點A ? ? ? 節點B ? ? ? 節點C
[prev|data|next] → [prev|data|next] → [prev|data|next]
? ?↑_______________________________↓
六、最佳實踐建議
1. 初始化容量:
java

復制

下載
// ArrayList預分配空間
List<String> arrayList = new ArrayList<>(1000);

// LinkedList無需預分配
List<String> linkedList = new LinkedList<>();
2. 遍歷優化:
java

復制

下載
// 避免使用隨機訪問遍歷LinkedList
// 錯誤方式:O(n2)
for (int i = 0; i < list.size(); i++) {
? ? list
.get(i);?
}

// 正確方式:使用迭代器 O(n)
for (Iterator it = list.iterator(); it.hasNext();) {
? ? it
.next();
}
3. 批量操作:
java

復制

下載
// ArrayList批量插入優化
arrayList
.addAll(index, collection); // 一次性移動元素

// LinkedList避免在中間批量插入
4. 線程安全:
java

復制

下載
// 兩者都非線程安全,需要同步
List syncList = Collections.synchronizedList(new ArrayList());
七、特殊場景分析
1. 內存碎片問題:
? ArrayList:內存連續,GC友好
? LinkedList:節點分散,可能引起內存碎片
2. CPU緩存友好性:
? ArrayList:數據局部性好,CPU緩存命中率高
? LinkedList:節點分散,緩存命中率低
3. 大型對象存儲:
? ArrayList:適合存儲小型對象
? LinkedList:更適合存儲大型對象(減少數組復制開銷)
八、JDK優化趨勢
在較新JDK版本中(Java 11+):
1. ArrayList在插入時采用更智能的擴容策略
2. LinkedList優化了迭代器實現
3. 新增List.of()創建不可變列表(底層實現根據大小自動選擇)
總結選擇指南
1. 80%場景選擇ArrayList - 現代CPU緩存優化使數組結構在多數操作中表現優異
2. 特定場景選擇LinkedList:
? 實現先進先出(FIFO)隊列
? 實現后進先出(LIFO)棧
? 需要頻繁在列表頭部操作
? 元素數量變化極大且無法預估
最終建議:在不確定時優先使用ArrayList,僅在明確需要LinkedList特性時才使用它。JDK自身的實現(如ArrayDeque)也傾向于使用數組結構而非鏈表。

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

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

相關文章

明遠智睿SD2351核心板:邊緣計算時代的工業級核心引擎深度解析

在工業4.0與物聯網深度融合的背景下&#xff0c;邊緣計算設備正從單一功能模塊向高集成度、智能化平臺演進。明遠智睿推出的SD2351核心板&#xff0c;憑借其異構計算架構、工業級接口資源和全棧技術生態&#xff0c;重新定義了邊緣計算設備的性能邊界。本文將從技術架構、場景適…

Flask 動態模塊注冊

目錄 1. 項目概述2. 項目結構3. 核心組件解析3.1 動態模塊注冊系統 (api/__init__.py)3.2 應用程序入口 (setup_demo.py) 4. 模塊開發指南4.1 標準模塊 (*_app.py)4.2 SDK模塊 (sdk/*.py) 5. URL路徑規則6. 如何使用6.1 啟動應用6.2 添加新模塊 7. 工作原理 1. 項目概述 這個項…

JVM 內存、JMM內存與集群機器節點內存的聯系

目錄 1、JVM 內存 1.1、分配機制 1.2、jvm模型位置 1.3、字節碼內存塊 2、JMM內存 2.1、JMM模型 2.2、工作流程圖 1、工作內存與主內存的交互 2. 多線程下的主內存與堆內存交互 2.3、 主內存與工作內存的同步方案 1、volatile 2、synchronized 3、final 3、內存使…

學習昇騰開發的第一天--環境配置

1、昇騰社區官網&#xff1a;昇騰社區官網-昇騰萬里 讓智能無所不及 2、產品-->選擇開發者套件-->點擊制卡工具的下載&#xff1a;資源-Atlas 200I DK A2-昇騰社區 3、如果制卡工具不能使用在線制卡&#xff0c;可以下載鏡像到本地使用本地制卡&#xff1a;Linux系統制…

Android WebView 深色模式適配方案總結

Android WebView 深色模式適配方案總結 在 Android WebView 中適配深色模式&#xff08;Dark Mode&#xff09;是一個常見的需求&#xff0c;尤其是當加載的網頁沒有原生支持 prefers-color-scheme 時。本文將介紹 3 種主流方案&#xff0c;并分析它們的優缺點&#xff0c;幫助…

項目練習:使用mybatis的foreach標簽,實現union all的拼接語句

文章目錄 一、需求說明二、需求分析三、代碼實現四、報表效果 一、需求說明 在sql查詢數據后&#xff0c;對數據分組統計。并最后進行總計。 二、需求分析 最終&#xff0c;我想用sql來實現這個統計和查詢的功能。 那么&#xff0c;怎么又查詢&#xff0c;又統計了&#xf…

7.7 Extracting and saving responses

Chapter 7-Fine-tuning to follow instructions 7.7 Extracting and saving responses 在本節中&#xff0c;我們保存測試集響應以便在下一節中評分&#xff0c;除此之外保存模型的副本以供將來使用。 ? 首先&#xff0c;讓我們簡單看看finetuned模型生成的響應 torch.manu…

計算機網絡第3章(上):數據鏈路層全解析——組幀、差錯控制與信道效率

目錄 一、數據鏈路層的功能二、組幀2.1 字符計數法&#xff08;Character Count&#xff09;2.2 字符填充法&#xff08;Character Stuffing&#xff09;2.3 零比特填充法2.4 違規編碼法 三、差錯控制3.1 檢錯編碼&#xff08;奇偶校驗碼&#xff09;3.2 循環冗余校驗&#xff…

鑄鐵試驗平臺的重要性及應用前景

鑄鐵作為一種重要的金屬材料&#xff0c;在工業生產中扮演著舉足輕重的角色。為了確保鑄鐵制品的質量和性能&#xff0c;鑄鐵材料的試驗是必不可少的環節。而鑄鐵試驗平臺則是進行鑄鐵試驗的關鍵設備之一&#xff0c;它為鑄鐵材料的研究和開發提供了重要的技術支持。本文將探討…

std::shared_ptr引起內存泄漏的例子

目錄 一、循環引用&#xff08;最常見場景&#xff09; 示例代碼 內存泄漏原因 二、共享指針管理的對象包含自身的 shared_ptr 示例代碼 內存泄漏&#xff08;或雙重釋放&#xff09;原因 三、解決方案 1. 循環引用&#xff1a;使用 std::weak_ptr 2. 對象獲取自身的 …

AI 知識數據庫搭建方案:從需求分析到落地實施

AI 知識數據庫的搭建需結合業務場景、數據特性與技術架構&#xff0c;形成系統化解決方案。以下是一套完整的搭建框架&#xff0c;涵蓋規劃、設計、實施及優化全流程&#xff1a; 一、前期規劃&#xff1a;需求分析與目標定義 1. 明確業務場景與知識需求 場景導向&#xff1a…

Tensorflow 基礎知識:變量、常量、占位符、Session 詳解

在深度學習領域,TensorFlow 是一個廣泛使用的開源機器學習框架。想要熟練使用 TensorFlow 進行模型開發,掌握變量、常量、占位符和 Session 這些基礎知識是必不可少的。接下來,我們就深入了解一下它們的概念、用處,并通過代碼示例進行演示。 一、常量(Constant) 常量,顧…

linux 常見問題之如何清除大文件的內容

linux 常見問題之如何清除大文件的內容 在 Linux 系統中&#xff0c;我們有時會遇到文件隨著時間增長變得巨大&#xff0c;最常見的就是服務器的日志文件&#xff0c;隨著時間的推移占用大量的磁盤空間&#xff0c;下面介紹如何清楚大文件的內容&#xff0c;當然避免文件內容過…

薛定諤的貓思想實驗如何推演到量子計算

前言 這是我的選修課作業&#xff0c;但是我并不喜歡小論文方式的寫法&#xff0c;死板又老套。先在這打一份底稿。 薛定諤的貓 可能一說到量子這個關鍵詞&#xff0c;大家第一時間都會想到的是“薛定諤的貓”。 實驗介紹 薛定諤的貓是一個著名的思想實驗&#xff0c;由奧…

嵌入式開發中fmacro-prefix-map選項解析

在嵌入式開發中&#xff0c;-fmacro-prefix-map 是 GCC 和 Clang 等編譯器提供的一個路徑映射選項&#xff0c;主要用于在預處理階段重寫宏定義中出現的絕對路徑。它的核心目的是解決以下問題&#xff1a; 核心作用 構建可重現性 消除編譯輸出&#xff08;如 .o、.d 文件&…

Javaweb學習——day3(Servlet 中處理表單數據)

文章目錄 一、概念學習1. GET vs POST 請求方式的區別2. HttpServletRequest 獲取表單數據 二、代碼講解與練習第 1 步&#xff1a;在 webapp 下創建 login.html第 2 步&#xff1a;在 com.example 包下創建 LoginServlet第 3 步&#xff1a;修改 web.xml 注冊 LoginServlet第 …

在 iOS 開發中單獨解析域名為 IP

1 為什么要自己解析? 典型場景說明劫持/污染檢測比較 系統解析 與 自建 DNS 的差異QoS / CDN 選路對每個候選 IP 做 RT/丟包測速系統 API(NSURLSession / Network.framework)在「真正建立連接之前」不會把解析結果暴露出來,因此需要主動解析一步。 2 API 選型概覽 API是否過…

YOLOv1 技術詳解:正負樣本劃分與置信度設計

&#x1f50d; YOLOv1 技術詳解&#xff1a;正負樣本劃分與置信度設計 一、前言 YOLOv1 是目標檢測領域中具有劃時代意義的算法之一&#xff0c;它將檢測任務統一為一個回歸問題&#xff0c;實現了“You Only Look Once”的端到端實時檢測。其中&#xff0c;正負樣本的劃分機…

為 Nginx 配置 HTTPS(以 n8n 為例)完整教程【CentOS 7】

在部署如 n8n 這類自動化平臺時&#xff0c;為了保障數據傳輸安全&#xff0c;我們通常會使用 HTTPS 訪問。本文將以 n8n.example.com 為例&#xff0c;介紹如何在 CentOS 7 系統中通過 Nginx 為本地運行在端口 5678 的 n8n 服務配置免費 SSL 證書&#xff08;Let’s Encrypt&a…

Elasticsearch從安裝到實戰、kibana安裝以及自定義IK分詞器/集成整合SpringBoot詳細的教程ES(四)查詢、排序、分頁、高亮

基礎代碼 package com.test.xulk;import com.alibaba.fastjson.JSON; import com.test.xulk.es.esdoc.HotelDoc; import com.test.xulk.es.service.IHotelService; import org.apache.http.HttpHost; import org.elasticsearch.action.search.SearchRequest; import org.elast…