Java集合面试题 - Java 中的List接口有哪些实现类?
List 接口概述
List 接口是 Java 集合框架中最常用的接口之一,它继承自 Collection 接口,代表有序的集合(也称为序列)。List 允许重复元素,并且可以通过索引精确控制每个元素的插入位置。
主要实现类介绍
ArrayList
ArrayList 是基于动态数组的实现,是最常用的 List 实现类。
特点:
- 基于动态数组,容量可自动增长
- 随机访问快(O(1))
- 插入和删除相对较慢(O(n))
- 非线程安全
示例代码:
import java.util.ArrayList;
import java.util.List;
public class ArrayListExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
// 添加元素
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
// 随机访问
System.out.println("Second element: " + fruits.get(1));
// 遍历
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
LinkedList
LinkedList 是基于双向链表的实现。
特点:
- 基于双向链表数据结构
- 插入和删除快(O(1))
- 随机访问慢(O(n))
- 实现了 Deque 接口,可以用作队列或双端队列
- 非线程安全
示例代码:
import java.util.LinkedList;
import java.util.List;
public class LinkedListExample {
public static void main(String[] args) {
List<String> colors = new LinkedList<>();
// 添加元素
colors.add("Red");
colors.add("Green");
colors.add("Blue");
// 在头部插入
((LinkedList<String>) colors).addFirst("Yellow");
// 在尾部插入
((LinkedList<String>) colors).addLast("Black");
// 移除第一个元素
String first = ((LinkedList<String>) colors).removeFirst();
System.out.println("Removed: " + first);
}
}
Vector
Vector 是一个古老的集合类,与 ArrayList 类似,但是线程安全的。
特点:
- 基于动态数组
- 所有方法都是同步的(线程安全)
- 性能比 ArrayList 差
- 有额外的遗留方法
示例代码:
import java.util.Vector;
import java.util.List;
public class VectorExample {
public static void main(String[] args) {
List<Integer> numbers = new Vector<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
// 使用遗留方法
((Vector<Integer>) numbers).addElement(40);
System.out.println("Capacity: " + ((Vector<Integer>) numbers).capacity());
}
}
Stack
Stack 继承自 Vector,实现了后进先出(LIFO)的栈结构。
特点:
- 继承自 Vector
- 线程安全
- 提供 push, pop, peek 等栈操作
示例代码:
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
// 压栈
stack.push("First");
stack.push("Second");
stack.push("Third");
// 查看栈顶
System.out.println("Top: " + stack.peek());
// 弹栈
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
}
CopyOnWriteArrayList
线程安全的 List 实现,适合读多写少的场景。
特点:
- 线程安全
- 写操作时复制整个底层数组
- 读操作不需要加锁
- 迭代器不会抛出 ConcurrentModificationException
示例代码:
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");
list.add("C");
// 线程安全遍历
for (String item : list) {
System.out.println(item);
list.add("D"); // 不会抛出异常
}
}
}
实现类对比
| 特性 | ArrayList | LinkedList | Vector | Stack | CopyOnWriteArrayList |
|---|---|---|---|---|---|
| 底层数据结构 | 动态数组 | 双向链表 | 动态数组 | 动态数组 | 动态数组 |
| 线程安全 | 否 | 否 | 是 | 是 | 是 |
| 随机访问性能 | O(1) | O(n) | O(1) | O(1) | O(1) |
| 插入/删除性能 | O(n) | O(1) | O(n) | O(n) | O(n) |
| 内存占用 | 较低 | 较高 | 较低 | 较低 | 较高 |
| 迭代时修改 | 抛异常 | 抛异常 | 抛异常 | 抛异常 | 不抛异常 |
使用场景建议
- ArrayList:大多数情况下首选,特别是需要频繁随机访问时。
- LinkedList:需要频繁在列表中间插入/删除元素,或需要实现队列/双端队列功能时。
- Vector:需要线程安全且不介意性能损失时(现代代码中更推荐使用 Collections.synchronizedList 或 CopyOnWriteArrayList)。
- Stack:需要严格的 LIFO 栈结构时(现代代码中更推荐使用 Deque 接口的实现类)。
- CopyOnWriteArrayList:读多写少且需要线程安全的场景。
总结
Java 的 List 接口提供了多种实现类,每种实现都有其特定的优势和适用场景。理解这些实现类的底层原理和性能特征,能够帮助我们在实际开发中做出更合理的选择。在大多数情况下,ArrayList 是默认的选择,但在特定场景下,其他实现类可能更为合适。

678

被折叠的 条评论
为什么被折叠?



