在Java的集合框架中,ArrayList和LinkedList都是常用的List实现类。两者虽然都实现了 List 接口,但在底层数据结构、插入删除性能、随机访问性能等方面存在显著区别。本文将分析 ArrayList 和 LinkedList 的特点及区别。
1. ArrayList 和 LinkedList 的基本特点
1.1 ArrayList 的特点
- 基于动态数组实现,默认初始容量为10,当容量不够时,会扩容1.5倍。
- 支持快速随机访问,它基于数组,通过索引可以直接定位元素。
- 插入和删除效率低,特别是在中间位置插入或删除时,需要移动大量元素。
- 占用空间较小,仅存储元素数据,不额外存储节点信息。
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1); // 添加到末尾 O(1)
arrayList.add(2);
arrayList.add(3);
arrayList.get(1); // 获取索引1的元素 O(1)
arrayList.remove(0); // 删除索引0的元素 O(n)
1.2 LinkedList 的特点
- 基于双向链表实现,每个元素都是一个节点,包含
prev(前驱)、next(后继)指针。 - 随机访问性能较差,因为不能直接通过索引访问,需要从头或尾开始遍历。
- 插入和删除效率高,只需修改前后指针,不需要像
ArrayList一样移动数据。 - 额外的空间开销较大,每个节点除了存储数据,还需要存储
prev和next指针。
LinkedList<Integer> linkedList = new LinkedList<>();
linkedList.add(1); // 添加到末尾 O(1)
linkedList.add(2);
linkedList.add(3);
linkedList.get(1); // 获取索引1的元素 O(n)
linkedList.remove(0); // 删除索引0的元素 O(1)
linkedList.addFirst(0); // 添加到头部 O(1)
linkedList.removeLast(); // 删除尾部元素 O(1)
2. 代码分析:增删改查性能对比
2.1 随机访问性能
对于 ArrayList,可以直接通过索引访问元素,查询速度较快:
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
arrayList.add(i);
}
// 访问第 5 个元素
System.out.println("ArrayList 索引 5 的元素: " + arrayList.get(5));
}
}
对于 LinkedList,获取元素需要从头或尾开始查找:
import java.util.LinkedList;
public class LinkedListTest {
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < 10; i++) {
linkedList.add(i);
}
// 访问第 5 个元素
System.out.println("LinkedList 索引 5 的元素: " + linkedList.get(5));
}
}
结论:如果需要频繁查询元素,ArrayList 速度更快。
2.2 插入和删除
在 ArrayList 中,插入或删除元素时,如果位置在中间或头部,后续的元素都需要移动,影响性能:
import java.util.ArrayList;
public class ArrayListInsertTest {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
arrayList.add(i);
}
// 在索引 2 处插入一个元素
arrayList.add(2, 99);
System.out.println(arrayList); // [0, 1, 99, 2, 3, 4]
}
}
在 LinkedList 中,插入操作不会影响其他元素,只需修改指针:
import java.util.LinkedList;
public class LinkedListInsertTest {
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < 5; i++) {
linkedList.add(i);
}
// 在索引 2 处插入一个元素
linkedList.add(2, 99);
System.out.println(linkedList); // [0, 1, 99, 2, 3, 4]
}
}
结论:在中间或头部插入/删除元素时,LinkedList 更高效,但如果是末尾添加,ArrayList 仍然更快。
3. ArrayList vs LinkedList 的使用场景
| 操作类型 | ArrayList | LinkedList |
|---|---|---|
| 查询(get) | 快,可以直接访问 | 慢,需要遍历查找 |
| 插入/删除(中间/头部) | 慢,需要移动元素 | 快,只需修改指针 |
| 插入/删除(尾部) | 快 | 快 |
| 占用空间 | 较小,仅存储数据 | 较大,需要额外存储指针 |
推荐使用场景
-
ArrayList适合:需要频繁查询数据的场景,如读取操作较多的情况。 -
LinkedList适合:需要频繁插入/删除的场景,尤其是在列表中间或头部插入/删除元素时更合适。
4. 结论
-
ArrayList基于数组,适合查询操作多的场景,但在插入和删除方面较慢。 -
LinkedList基于双向链表,适合频繁插入和删除的场景,但查询性能较差。
一般情况下,如果没有特殊需求,建议使用 ArrayList,因为它的查询速度快,而且在大多数情况下,插入/删除的性能不会有太大影响。

962





