一、集合框架概述
Java集合框架(Java Collections Framework, JCF)是Java中用于存储、操作和管理数据集合的标准化架构。它通过统一的接口和实现类,提供高效的数据结构和算法支持。
核心组成:
- 接口:定义集合的抽象行为(如
Collection,List,Set,Map)。 - 实现类:接口的具体实现(如
ArrayList,HashSet,HashMap)。 - 算法:工具类
Collections提供的排序、查找等通用操作。 - 迭代器:
Iterator和ListIterator,用于遍历集合元素。
二、核心接口与实现类
1. Collection接口
- 定义:所有集合类的根接口(除了
Map)。 - 核心子接口:
List:有序集合,允许重复元素。Set:无序集合,不允许重复元素。Queue:队列,支持先进先出(FIFO)或优先级操作。
boolean add(E e); // 添加元素
boolean remove(Object o); // 删除元素
int size(); // 返回元素数量
Iterator<E> iterator(); // 获取迭代器
2. List接口
特点:有序、可重复、支持索引访问。
| 实现类 | 数据结构 | 线程安全 | 适用场景 |
|---|---|---|---|
| ArrayList | 动态数组 | 否 | 频繁查询,较少插入删除 |
| LinkedList | 双向链表 | 否 | 频繁插入删除,较少查询 |
| Vector | 动态数组 | 是 | 遗留类,已被ArrayList替代 |
| CopyOnWriteArrayList | 写时复制数组 | 是 | 读多写少的高并发场景 |
List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.get(0); // 通过索引访问
List<String> linkedList = new LinkedList<>();
linkedList.addFirst("First"); // 链表头插入
3. Set接口
特点:无序、元素唯一。
| 实现类 | 数据结构 | 排序 | 线程安全 |
|---|---|---|---|
| HashSet | 哈希表 | 无 | 否 |
| LinkedHashSet | 哈希表+链表 | 插入顺序 | 否 |
| TreeSet | 红黑树 | 自然排序 | 否 |
| CopyOnWriteArraySet | 写时复制数组 | 无 | 是 |
Set<Integer> hashSet = new HashSet<>();
hashSet.add(1);
hashSet.add(1); // 重复元素被忽略
Set<String> treeSet = new TreeSet<>();
treeSet.add("Banana"); // 自动按字典序排序
4. Queue接口
特点:队列操作,支持FIFO或优先级。
| 实现类 | 数据结构 | 特性 |
|---|---|---|
| LinkedList | 链表 | 可用作普通队列 |
| PriorityQueue | 堆(数组实现) | 元素按优先级排序 |
| ArrayDeque | 动态数组 | 双端队列,高效头尾操作 |
| BlockingQueue | 多种实现 | 线程安全的阻塞队列 |
Queue<Integer> queue = new LinkedList<>();
queue.offer(1); // 入队
queue.poll(); // 出队
Queue<Integer> priorityQueue = new PriorityQueue<>();
priorityQueue.offer(3);
priorityQueue.offer(1); // 自动按升序排序
5. Map接口
特点:键值对存储,键唯一。
| 实现类 | 数据结构 | 线程安全 | 排序特性 |
|---|---|---|---|
| HashMap | 哈希表 | 否 | 无序 |
| LinkedHashMap | 哈希表+链表 | 否 | 插入顺序/访问顺序 |
| TreeMap | 红黑树 | 否 | 键自然排序 |
| Hashtable | 哈希表 | 是 | 遗留类 |
| ConcurrentHashMap | 分段锁哈希表 | 是 | 高并发优化 |
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Java", 1);
hashMap.get("Java"); // 返回值1
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("Banana", 2); // 按键字典序排序
三、集合工具类Collections
提供静态方法操作集合,常见功能包括:
- 排序:
sort(List<T> list) - 查找:
binarySearch(List<T> list, T key) - 同步包装:
synchronizedList(List<T> list) - 不可变集合:
unmodifiableList(List<T> list)
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 2));
Collections.sort(list); // [1, 2, 3]
List<Integer> syncList = Collections.synchronizedList(list); // 线程安全包装
四、迭代器与遍历
1.Iterator接口:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String element = it.next();
it.remove(); // 安全删除当前元素
}
2.ListIterator接口:
- 支持双向遍历(
hasPrevious(),previous())。 - 允许在遍历时修改列表(
add(),set())。
3. 增强for循环:
for (String s : list) {
System.out.println(s);
}
五、Java 8+ 新特性
1. Lambda表达式与集合操作:
list.forEach(element -> System.out.println(element));
list.removeIf(element -> element.length() < 3);
2. Stream API:
List<String> filtered = list.stream()
.filter(s -> s.startsWith("A"))
.sorted()
.collect(Collectors.toList());
3. 新的集合工厂方法(Java 9+):
List<String> immutableList = List.of("A", "B", "C"); // 不可变集合
Map<String, Integer> immutableMap = Map.of("Java", 1, "C++", 2);
六、性能与选择指南
| 场景 | 推荐实现类 | 原因 |
|---|---|---|
| 频繁查询 | ArrayList | 动态数组支持O(1)随机访问 |
| 频繁插入删除 | LinkedList | 链表操作时间复杂度O(1) |
| 需要唯一元素 | HashSet | 哈希表实现O(1)查找 |
| 需要排序 | TreeSet/TreeMap | 红黑树支持自然排序 |
| 高并发读多写少 | CopyOnWriteArrayList | 写时复制保证线程安全 |
| 高并发读写 | ConcurrentHashMap | 分段锁优化并发性能 |
七、常见问题与解决方案
1. ConcurrentModificationException
- 原因:遍历集合时直接修改集合结构(如删除元素)。
- 解决:使用迭代器的
remove()方法,或CopyOnWriteArrayList。
2. 选择HashMap还是Hashtable
HashMap:非线程安全,性能更高。ConcurrentHashMap:替代Hashtable,支持高并发。
3. 集合与数组转换
String[] array = list.toArray(new String[0]); // List转数组
List<String> list = Arrays.asList(array); // 数组转List(固定大小)
八、集合存储原理
1. ArrayList(动态数组)
- 数据结构:基于数组实现,支持动态扩容。
- 存储机制:
- 初始化:默认容量为
10,可指定初始容量。 - 扩容:当元素数量超过当前容量时,容量扩展为原来的
1.5倍(int newCapacity = oldCapacity + (oldCapacity >> 1))。 - 内存分配:每次扩容时创建新数组并复制旧数据,时间复杂度为
O(n)。
- 初始化:默认容量为
- 操作复杂度:
- 访问:
O(1)(通过索引直接定位)。 - 插入/删除:
O(n)(需要移动后续元素)。
- 访问:
ArrayList<Integer> list = new ArrayList<>();
list.add(1); // 初始容量为10
for (int i = 0; i < 15; i++) list.add(i); // 触发扩容至15
3.LinkedList(双向链表)
- 数据结构:每个节点(
Node)包含前驱、后继指针和元素值。 - 存储机制:
- 插入/删除:只需修改相邻节点的指针,时间复杂度
O(1)(已知位置时)。 - 访问:需从头或尾遍历链表,时间复杂度
O(n)。
- 插入/删除:只需修改相邻节点的指针,时间复杂度
- 内存占用:每个元素需额外存储两个指针,空间复杂度高于
ArrayList。
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
}
3.HashMap(哈希表+链表/红黑树)
-
数据结构:数组(桶) + 链表或红黑树(解决哈希冲突)。
-
存储机制:
- 哈希函数:
key.hashCode()的高16位异或低16位,均匀分布哈希值。 - 桶定位:
index = (n - 1) & hash,其中n为桶数组长度(2的幂)。 - 冲突解决:
- 哈希函数:
-
链表:当链表长度≥8且桶数量≥64时,链表转为红黑树(时间复杂度从
O(n)优化为O(log n))。 -
红黑树:当红黑树节点≤6时,退化为链表。
-
扩容:默认负载因子
0.75,当元素数超过容量*负载因子时,容量翻倍并重新哈希。
操作复杂度:
- 插入/查找/删除:平均
O(1),最坏O(log n)(红黑树)。
HashMap<String, Integer> map = new HashMap<>();
map.put("Java", 1); // 哈希值为"Java".hashCode()
4. TreeSet(红黑树)
- 数据结构:基于
TreeMap实现,使用红黑树保持元素有序。 - 存储机制:
- 排序规则:自然排序(
Comparable)或自定义比较器(Comparator)。 - 插入/删除:通过红黑树自平衡保证操作复杂度为
O(log n)。
- 排序规则:自然排序(
- 内存占用:每个节点需存储父节点、左右子节点指针及颜色标记。
TreeSet<Integer> treeSet = new TreeSet<>((a, b) -> b - a); // 降序排列
treeSet.add(3); // 插入时自动调整树结构
九、集合遍历机制
1. 迭代器(Iterator)
- 实现原理:
ArrayList:通过索引直接访问元素。LinkedList:记录当前遍历的节点指针。HashMap:依次遍历桶数组中的链表或红黑树。
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String element = it.next();
it.remove(); // 安全删除当前元素
}
- Fail-Fast机制:
- 遍历时若集合被修改(非通过迭代器自身方法),抛出
ConcurrentModificationException。 - 实现方式:检查
modCount(修改计数器)是否与预期值一致。
- 遍历时若集合被修改(非通过迭代器自身方法),抛出
2. 增强for循环
- 底层实现:编译后转换为迭代器遍历。
// 源码
for (String s : list) { ... }
// 编译后等效代码
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
...
}
3. ListIterator(双向遍历)
- 特性:
- 支持向前(
hasPrevious(),previous())和向后遍历。 - 允许在遍历时修改列表(
add(),set())。
- 支持向前(
- 应用场景:需要反向遍历或边遍历边修改。
ListIterator<String> lit = list.listIterator(list.size());
while (lit.hasPrevious()) {
String prev = lit.previous();
}
十、不同集合遍历性能对比
| 集合类型 | 遍历方式 | 时间复杂度 | 适用场景 |
|---|---|---|---|
| ArrayList | 索引for循环 | O(n) | 频繁随机访问 |
| LinkedList | 迭代器 | O(n) | 避免使用索引遍历(O(n^2)) |
| HashSet | 迭代器 | O(n) | 无序遍历 |
| LinkedHashSet | 迭代器 | O(n) | 按插入顺序遍历 |
| TreeSet | 迭代器 | O(n) | 按排序顺序遍历 |
| HashMap | 迭代器(EntrySet) | O(n) | 遍历键值对 |
十一、遍历中的常见问题与解决方案
1. ConcurrentModificationException
- 原因:在遍历过程中直接调用集合的
add()或remove()方法。 - 解决:使用迭代器的
remove()方法或CopyOnWriteArrayList。
2. 遍历删除元素
// 错误方式
for (String s : list) {
if (s.equals("Java")) list.remove(s); // 抛出异常
}
// 正确方式
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (it.next().equals("Java")) it.remove();
}
3. 遍历大型集合优化
- 使用
Stream的并行流加速处理
list.parallelStream().forEach(...);
1373

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



