Java中ArrayList和LinkedList有什么區(qū)別舉例詳解
一、底層數(shù)據(jù)結(jié)構(gòu)
特性 | ArrayList | LinkedList |
---|---|---|
實(shí)現(xiàn)方式 | 基于動(dòng)態(tài)數(shù)組 | 基于雙向鏈表 |
內(nèi)存布局 | 連續(xù)內(nèi)存塊,支持快速隨機(jī)訪(fǎng)問(wèn) | 離散節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)包含數(shù)據(jù)及前后指針 |
默認(rèn)初始容量 | 10(擴(kuò)容時(shí)增長(zhǎng) 50%) | 無(wú)預(yù)分配容量,動(dòng)態(tài)添加節(jié)點(diǎn) |
二、核心操作性能對(duì)比
// ArrayList的隨機(jī)訪(fǎng)問(wèn)示例 ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(1); int val1 = arrayList.get(0); // O(1) // LinkedList的順序訪(fǎng)問(wèn)示例 LinkedList<Integer> linkedList = new LinkedList<>(); linkedList.add(1); int val2 = linkedList.get(0); // O(n)
操作 | ArrayList 時(shí)間復(fù)雜度 | LinkedList 時(shí)間復(fù)雜度 |
---|---|---|
隨機(jī)訪(fǎng)問(wèn)(get/set) | O(1) | O(n) |
頭部插入/刪除 | O(n)(需移動(dòng)元素) | O(1) |
尾部插入/刪除 | 分?jǐn)?O(1)(無(wú)擴(kuò)容時(shí) O(1)) | O(1) |
中間插入/刪除 | O(n) | O(n)(需遍歷到目標(biāo)位置) |
三、內(nèi)存與 GC 影響
維度 | ArrayList | LinkedList |
---|---|---|
內(nèi)存占用 | 僅存儲(chǔ)元素 + 數(shù)組頭(內(nèi)存緊湊) | 每個(gè)節(jié)點(diǎn)額外存儲(chǔ)兩個(gè)指針(對(duì)象頭 + 前后引用) |
GC 壓力 | 整體回收高效(單個(gè)數(shù)組對(duì)象) | 頻繁增刪產(chǎn)生大量小對(duì)象,增加 GC 負(fù)擔(dān) |
緩存局部性 | 高(連續(xù)內(nèi)存,CPU 預(yù)加載命中率高) | 低(節(jié)點(diǎn)分散,緩存未命中率高) |
四、擴(kuò)容機(jī)制
ArrayList 擴(kuò)容流程:
// 擴(kuò)容核心邏輯(JDK17) int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5倍擴(kuò)容 elementData = Arrays.copyOf(elementData, newCapacity);
- 代價(jià):數(shù)據(jù)復(fù)制導(dǎo)致 O(n) 時(shí)間復(fù)雜度
- 優(yōu)化建議:初始化時(shí)預(yù)估容量(
new ArrayList<>(initialCapacity)
)
LinkedList 無(wú)擴(kuò)容:動(dòng)態(tài)添加節(jié)點(diǎn),但每個(gè)節(jié)點(diǎn)額外占用 24 字節(jié)(64 位 JVM)
五、線(xiàn)程安全與并發(fā)方案
方案 | ArrayList | LinkedList |
---|---|---|
默認(rèn)線(xiàn)程安全 | 否 | 否 |
同步包裝類(lèi) | Collections.synchronizedList() | Collections.synchronizedList() |
高并發(fā)替代方案 | CopyOnWriteArrayList | ConcurrentLinkedDeque |
六、工程實(shí)踐場(chǎng)景
1. 電商商品列表展示
選擇 ArrayList:
- 高頻讀取商品信息(隨機(jī)訪(fǎng)問(wèn))
- 批量更新時(shí)通過(guò)尾插法優(yōu)化(
addAll()
)
List<Product> products = new ArrayList<>(10000); // 預(yù)分配容量
2. 實(shí)時(shí)消息隊(duì)列
選擇 LinkedList:
- 高頻頭尾操作(
addFirst()
/removeLast()
) - 使用迭代器避免隨機(jī)訪(fǎng)問(wèn):
LinkedList<Message> queue = new LinkedList<>(); // 生產(chǎn)者 queue.offer(new Message()); // 消費(fèi)者(高效遍歷) Iterator<Message> it = queue.iterator(); while(it.hasNext()) process(it.next());
- 高頻頭尾操作(
3. 多線(xiàn)程日志處理器
選擇 CopyOnWriteArrayList:
- 寫(xiě)操作極少(日志初始化配置)
- 高頻遍歷讀取日志規(guī)則
CopyOnWriteArrayList<LogRule> rules = new CopyOnWriteArrayList<>(); // 寫(xiě)操作(僅在配置更新時(shí)觸發(fā)) rules.add(new LogRule()); // 讀操作(無(wú)鎖并發(fā)) rules.forEach(LogService::applyRule);
七、性能對(duì)比測(cè)試數(shù)據(jù)
測(cè)試環(huán)境:JDK17,10 萬(wàn)次操作,i7-11800H
測(cè)試場(chǎng)景 | ArrayList 耗時(shí) | LinkedList 耗時(shí) | 差異原因 |
---|---|---|---|
隨機(jī)訪(fǎng)問(wèn) 1 萬(wàn)次 | 2ms | 650ms | 數(shù)組 O(1) vs 鏈表 O(n) 遍歷 |
尾部插入 1 萬(wàn)次 | 3ms | 5ms | 均攤 O(1),鏈表節(jié)點(diǎn)創(chuàng)建開(kāi)銷(xiāo)略高 |
頭部插入 1 萬(wàn)次 | 420ms | 8ms | 數(shù)組需移動(dòng)元素,鏈表直接修改指針 |
遍歷所有元素 | 15ms | 18ms | 數(shù)組緩存命中率高 |
八、高級(jí)特性對(duì)比
特性 | ArrayList | LinkedList |
---|---|---|
實(shí)現(xiàn)接口 | List | List + Deque |
序列化效率 | 高(連續(xù)數(shù)據(jù),可批量寫(xiě)入) | 低(需逐個(gè)節(jié)點(diǎn)處理) |
內(nèi)存池兼容性 | 適合對(duì)象池化(數(shù)組整體復(fù)用) | 節(jié)點(diǎn)分散,池化效果差 |
批量操作優(yōu)化 | System.arraycopy() 高效 | 需要逐個(gè)節(jié)點(diǎn)操作 |
九、選型決策樹(shù)
通過(guò)以上對(duì)比,開(kāi)發(fā)者可根據(jù)具體場(chǎng)景選擇最合適的實(shí)現(xiàn):
- 優(yōu)先 ArrayList:適用于 90% 的常規(guī)場(chǎng)景(讀多寫(xiě)少、內(nèi)存敏感)
- 慎用 LinkedList:僅在需要頻繁頭尾操作或?qū)崿F(xiàn)雙端隊(duì)列時(shí)選用
- 線(xiàn)程安全場(chǎng)景:根據(jù)寫(xiě)頻率選擇
CopyOnWriteArrayList
或同步包裝類(lèi)
結(jié)論
ArrayList 更適合:如果你的操作主要集中在隨機(jī)訪(fǎng)問(wèn)和列表末尾的插入刪除,且你希望節(jié)省內(nèi)存,
ArrayList
是首選。LinkedList 更適合:如果你的操作主要是頻繁在列表中間進(jìn)行插入和刪除,而隨機(jī)訪(fǎng)問(wèn)較少,
LinkedList
會(huì)表現(xiàn)得更好。
總結(jié)
到此這篇關(guān)于Java中ArrayList和LinkedList有什么區(qū)別的文章就介紹到這了,更多相關(guān)Java中ArrayList和LinkedList區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java中ArrayList和LinkedList的區(qū)別詳解
- 淺談 java中ArrayList、Vector、LinkedList的區(qū)別聯(lián)系
- 淺析 ArrayList 和 LinkedList 有什么區(qū)別
- ArrayList和LinkedList區(qū)別及使用場(chǎng)景代碼解析
- Java中ArrayList和LinkedList之間的區(qū)別_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- Java面試崗常見(jiàn)問(wèn)題之ArrayList和LinkedList的區(qū)別
- Java ArrayList與LinkedList及HashMap容器的用法區(qū)別
- Java中ArrayList和LinkedList的區(qū)別
- Java中ArrayList和LinkedList區(qū)別
- ArrayList與linkedList的用法區(qū)別及擴(kuò)容方式
相關(guān)文章
Java中的線(xiàn)程中斷機(jī)制和LockSupport詳解
這篇文章主要介紹了Java中的線(xiàn)程中斷機(jī)制和LockSupport詳解,在Java中沒(méi)有辦法立即停止一條線(xiàn)程,然而停止線(xiàn)程卻顯得尤為重要,如取消一個(gè)耗時(shí)操作,因此,Java提供了一種用于停止線(xiàn)程的協(xié)商機(jī)制中斷,也即中斷標(biāo)識(shí)協(xié)商機(jī)制,需要的朋友可以參考下2023-09-09Springboot項(xiàng)目啟動(dòng)不加載resources目錄下的文件問(wèn)題
這篇文章主要介紹了Springboot項(xiàng)目啟動(dòng)不加載resources目錄下的文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08SpringBoot下使用自定義監(jiān)聽(tīng)事件的流程分析
事件機(jī)制是Spring的一個(gè)功能,目前我們使用了SpringBoot框架,所以記錄下事件機(jī)制在SpringBoot框架下的使用,同時(shí)實(shí)現(xiàn)異步處理,這篇文章主要介紹了SpringBoot下使用自定義監(jiān)聽(tīng)事件,需要的朋友可以參考下2023-08-08劍指Offer之Java算法習(xí)題精講鏈表專(zhuān)題篇
跟著思路走,之后從簡(jiǎn)單題入手,反復(fù)去看,做過(guò)之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化2022-03-03Java可變個(gè)數(shù)形參的方法實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于Java可變個(gè)數(shù)形參的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-02-02Spring RestTemplate簡(jiǎn)化HTTP通信實(shí)現(xiàn)功能探究
這篇文章主要為大家介紹了Spring框架中的RestTemplate,如果你是個(gè)Java程序員,那么你肯定知道Spring框架的重要性,在Spring的眾多工具中,RestTemplate是用來(lái)簡(jiǎn)化HTTP通信的一個(gè)強(qiáng)大工具2024-01-01