Java中的集合框架List接口详解
字数 869 2025-11-04 20:48:29
Java中的集合框架List接口详解
一、List接口的基本概念
List是Java集合框架中最常用的接口之一,它继承自Collection接口,代表一个有序的集合(也称为序列)。与Set不同,List允许存储重复元素,并且通过整数索引可以精确控制每个元素的插入位置。
二、List接口的核心特性
- 有序性:元素按照插入顺序排列,可以通过索引(从0开始)访问
- 元素可重复:允许存储相同的元素(通过equals()方法判断)
- 允许null元素:可以包含一个或多个null值
- 索引访问:提供基于位置的索引操作方法
三、List接口的主要实现类
3.1 ArrayList
- 底层实现:基于动态数组
- 特点:随机访问快(O(1)),但插入删除效率较低(需要移动元素)
- 扩容机制:默认初始容量10,扩容时增加为原来的1.5倍
示例代码分析:
List<String> list = new ArrayList<>();
list.add("A"); // 第一次添加,初始化数组容量为10
list.add("B");
list.add("C");
// 访问第二个元素 - 直接通过数组索引
String element = list.get(1); // 返回"B"
// 在指定位置插入元素
list.add(1, "X"); // 需要将"B","C"向后移动
3.2 LinkedList
- 底层实现:基于双向链表
- 特点:插入删除快(O(1)),但随机访问慢(需要遍历链表)
- 节点结构:每个节点包含前驱指针、数据、后继指针
链表操作原理:
初始链表:A ↔ B ↔ C
在B前插入X:
1. 创建新节点X
2. 将X的前驱指向A,后继指向B
3. 将A的后继指向X,将B的前驱指向X
结果:A ↔ X ↔ B ↔ C
3.3 Vector
- 历史遗留类,与ArrayList类似但线程安全
- 扩容机制:默认扩容为原来的2倍
- 已被Collections.synchronizedList()和CopyOnWriteArrayList替代
四、List接口的重要方法详解
4.1 基础操作方法
List<String> list = new ArrayList<>();
// 添加元素
list.add("Apple"); // 尾部添加
list.add(0, "Banana"); // 指定位置插入
// 获取元素
String fruit = list.get(0); // 返回"Banana"
// 删除元素
list.remove(0); // 删除索引0处的元素
list.remove("Apple"); // 删除第一个匹配的元素
// 修改元素
list.set(0, "Orange"); // 将索引0处元素替换为"Orange"
4.2 批量操作方法
List<String> list1 = Arrays.asList("A", "B", "C");
List<String> list2 = new ArrayList<>();
// 批量添加
list2.addAll(list1); // 将list1所有元素添加到list2
// 批量删除
list2.removeAll(list1); // 删除list2中所有在list1中出现的元素
// 保留交集
list2.retainAll(list1); // 只保留同时在两个列表中的元素
4.3 查找和遍历方法
List<String> list = Arrays.asList("A", "B", "C", "A");
// 查找元素
int index = list.indexOf("A"); // 返回0,第一次出现的位置
int lastIndex = list.lastIndexOf("A"); // 返回3,最后一次出现的位置
boolean contains = list.contains("B"); // true
// 遍历方式
// 1. for循环(随机访问快的集合推荐)
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 2. 增强for循环
for (String element : list) {
System.out.println(element);
}
// 3. 迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
五、性能对比与选择策略
5.1 时间复杂度对比
操作 ArrayList LinkedList
get(index) O(1) O(n)
add(E) O(1)摊销 O(1)
add(index,E) O(n) O(1)(如果已知位置)
remove(index) O(n) O(1)(如果已知位置)
5.2 选择标准
- 频繁随机访问:选择ArrayList
- 频繁在头尾插入删除:选择LinkedList
- 多线程环境:考虑CopyOnWriteArrayList或同步包装
- 内存敏感:ArrayList通常比LinkedList更节省内存
六、使用注意事项
6.1 并发访问问题
// 非线程安全的操作
List<String> unsafeList = new ArrayList<>();
// 多线程环境下需要同步
List<String> safeList = Collections.synchronizedList(new ArrayList<>());
// 或者使用并发集合
CopyOnWriteArrayList<String> concurrentList = new CopyOnWriteArrayList<>();
6.2 迭代器使用规范
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
Iterator<String> iterator = list.iterator();
// 错误用法:在迭代过程中修改集合
while (iterator.hasNext()) {
String element = iterator.next();
if ("B".equals(element)) {
// list.remove(element); // 会抛出ConcurrentModificationException
iterator.remove(); // 正确用法:使用迭代器的remove方法
}
}
通过以上详细讲解,你应该对Java List接口有了全面的理解,包括其特性、实现原理、使用方法和适用场景。在实际开发中,根据具体需求选择合适的List实现类至关重要。