跳转到内容

Arraylist与linkedlist

来自代码酷

模板:Java基础导航

ArrayList与LinkedList[编辑 | 编辑源代码]

ArrayListLinkedList是Java集合框架中两种最常用的列表实现,均实现了List接口,但在底层数据结构、性能特性和适用场景上有显著差异。理解它们的区别对编写高效Java程序至关重要。

概述[编辑 | 编辑源代码]

  • ArrayList:基于动态数组实现,支持快速随机访问,但在中间插入/删除元素时效率较低。
  • LinkedList:基于双向链表实现,插入/删除高效,但随机访问性能较差。

底层数据结构[编辑 | 编辑源代码]

graph LR subgraph ArrayList A[Object数组] --> B[自动扩容] end subgraph LinkedList C[Node] --> D["prev|item|next"] D --> E[前驱节点] D --> F[后继节点] end

核心区别对比[编辑 | 编辑源代码]

ArrayList vs LinkedList 特性对比
特性 ArrayList LinkedList
动态数组 | 双向链表
O(1) | O(n)
O(n) | O(1)
O(1) 均摊 | O(1)
O(n) | O(1) 已知位置时
更小(仅存储数据) | 更大(额外存储节点信息)

代码示例[编辑 | 编辑源代码]

基础操作对比[编辑 | 编辑源代码]

import java.util.*;

public class ListComparison {
    public static void main(String[] args) {
        // 初始化
        List<Integer> arrayList = new ArrayList<>();
        List<Integer> linkedList = new LinkedList<>();

        // 尾部插入性能
        long start = System.nanoTime();
        for (int i = 0; i < 100000; i++) arrayList.add(i);
        System.out.println("ArrayList尾部插入: " + (System.nanoTime()-start)/1e6 + "ms");

        start = System.nanoTime();
        for (int i = 0; i < 100000; i++) linkedList.add(i);
        System.out.println("LinkedList尾部插入: " + (System.nanoTime()-start)/1e6 + "ms");

        // 随机访问性能
        start = System.nanoTime();
        arrayList.get(50000);
        System.out.println("ArrayList随机访问: " + (System.nanoTime()-start) + "ns");

        start = System.nanoTime();
        linkedList.get(50000);
        System.out.println("LinkedList随机访问: " + (System.nanoTime()-start) + "ns");
    }
}

输出示例

ArrayList尾部插入: 12.345ms
LinkedList尾部插入: 15.678ms
ArrayList随机访问: 150ns
LinkedList随机访问: 24500ns

扩容机制[编辑 | 编辑源代码]

ArrayList的扩容需要数学计算: newCapacity=oldCapacity+(oldCapacity>>1)

当添加元素超过当前容量时,ArrayList会创建一个新数组(大小为原数组的1.5倍),然后拷贝数据。

实际应用场景[编辑 | 编辑源代码]

  • 使用ArrayList
 * 频繁随机访问(如get(index))
 * 主要进行尾部操作
 * 内存敏感的应用
  • 使用LinkedList
 * 频繁在任意位置插入/删除
 * 实现队列/双端队列(实现了Deque接口)
 * 不需要大量随机访问

高级特性[编辑 | 编辑源代码]

LinkedList特有方法

LinkedList<String> list = new LinkedList<>();
list.addFirst("Head");  // 等同于push()
list.addLast("Tail");
String first = list.removeFirst(); // 等同于pop()
String last = list.removeLast();

性能分析[编辑 | 编辑源代码]

对于n个元素的操作时间复杂度:

时间复杂度对比
操作 ArrayList LinkedList
O(1) 均摊 | O(1)
O(n) | O(1) 已知节点时
O(n) | O(1) 已知节点时
O(1) | O(n)

内存布局可视化[编辑 | 编辑源代码]

graph TD subgraph ArrayList内存 A[引用1] --> B[连续内存块] C[引用2] --> B end subgraph LinkedList内存 D[引用1] --> E[节点A] E --> F[节点B] F --> G[节点C] G --> H[...] end

最佳实践建议[编辑 | 编辑源代码]

1. 默认首选ArrayList(大多数场景更优) 2. 只有在频繁在列表中间插入删除时才考虑LinkedList 3. 使用ListIterator可以改善LinkedList的遍历性能 4. 使用initialCapacity参数优化ArrayList初始化

模板:Java基础导航