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
// 添加元素
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
// 添加元素
colors.add("Red");
colors.add("Green");
colors.add("Blue");
// 在头部插入
((LinkedList
// 在尾部插入
((LinkedList
// 移除第一个元素
String first = ((LinkedList
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
numbers.add(10);
numbers.add(20);
numbers.add(30);
// 使用遗留方法
((Vector
System.out.println("Capacity: " + ((Vector
}
}
Stack
Stack 继承自 Vector,实现了后进先出(LIFO)的栈结构。
特点:
继承自 Vector线程安全提供 push, pop, peek 等栈操作
示例代码:
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
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
list.add("A");
list.add("B");
list.add("C");
// 线程安全遍历
for (String item : list) {
System.out.println(item);
list.add("D"); // 不会抛出异常
}
}
}
实现类对比
特性ArrayListLinkedListVectorStackCopyOnWriteArrayList底层数据结构动态数组双向链表动态数组动态数组动态数组线程安全否否是是是随机访问性能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 是默认的选择,但在特定场景下,其他实现类可能更为合适。