Java集合框架(Java Collections Framework)是Java中用于存储和操作数据集合的一组接口和类,提供了高效的数据结构和算法实现。
一、集合框架概述
1. 核心接口层次结构
Iterable (接口)
└── Collection (接口)
├── List (接口)
├── Set (接口)
│ └── SortedSet (接口)
└── Queue (接口)
└── Deque (接口)
Map (接口)
└── SortedMap (接口)
2. 主要实现类对比
接口 | 有序 | 允许重复 | 允许null | 线程安全 | 主要实现类 |
---|---|---|---|---|---|
List | 是 | 是 | 是 | 否 | ArrayList, LinkedList, Vector |
Set | 否* | 否 | 是** | 否 | HashSet, LinkedHashSet, TreeSet |
Queue | 是 | 是 | 是*** | 否 | LinkedList, PriorityQueue |
Map | 否* | key唯一 | key/value | 否 | HashMap, LinkedHashMap, TreeMap |
TreeSet/TreeMap是有序的;TreeSet不允许null元素;某些Queue实现不允许null
二、List接口及实现类
1. ArrayList
特点:
- 基于动态数组实现
- 随机访问快(O(1))
- 插入删除慢(O(n))
- 初始容量10,扩容1.5倍
常用方法:
List<String> list = new ArrayList<>();
list.add("A"); // 添加元素
list.add(1, "B"); // 指定位置插入
list.get(0); // 获取元素
list.remove(0); // 删除元素
list.set(0, "C"); // 修改元素
list.indexOf("B"); // 查找索引
list.subList(1, 3); // 获取子列表
2. LinkedList
特点:
- 基于双向链表实现
- 插入删除快(O(1))
- 随机访问慢(O(n))
- 实现了List和Deque接口
特有方法:
LinkedList<String> list = new LinkedList<>();
list.addFirst("A"); // 头部添加
list.addLast("B"); // 尾部添加
list.getFirst(); // 获取头部
list.getLast(); // 获取尾部
list.removeFirst(); // 移除头部
list.removeLast(); // 移除尾部
3. Vector vs ArrayList
特性 | Vector | ArrayList |
---|---|---|
同步 | 是(线程安全) | 否 |
扩容 | 默认2倍 | 1.5倍 |
迭代器 | Enumeration和Iterator | Iterator |
性能 | 较低 | 较高 |
遗留类 | 是 | 否 |
三、Set接口及实现类
1. HashSet
特点:
- 基于HashMap实现
- 无序集合
- 允许null元素
- 添加/删除/查找O(1)
示例:
Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.contains("A"); // true
set.remove("B");
2. LinkedHashSet
特点:
- 继承HashSet
- 维护插入顺序
- 性能略低于HashSet
3. TreeSet
特点:
- 基于TreeMap实现
- 元素按自然顺序或Comparator排序
- 基本操作O(log n)
示例:
Set<String> set = new TreeSet<>(Comparator.reverseOrder());
set.add("C");
set.add("A");
set.add("B");
// 结果为[C, B, A]
四、Map接口及实现类
1. HashMap
特点:
- 数组+链表+红黑树(JDK8+)
- 初始容量16,负载因子0.75
- 允许null键和null值
- 非线程安全
常用方法:
Map<String, Integer> map = new HashMap<>();
map.put("A", 1); // 添加键值对
map.get("A"); // 获取值
map.containsKey("A"); // 检查键
map.remove("A"); // 删除
map.keySet(); // 获取所有键
map.values(); // 获取所有值
map.forEach((k, v) -> System.out.println(k + ": " + v)); // 遍历
2. LinkedHashMap
特点:
- 继承HashMap
- 维护插入顺序或访问顺序
- 可用于实现LRU缓存
示例:
// 按访问顺序排序(最近最少使用在前)
Map<String, Integer> lruMap = new LinkedHashMap<>(16, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, Integer> eldest) {
return size() > 3; // 最大保留3个元素
}
};
3. TreeMap
特点:
- 基于红黑树实现
- 按键的自然顺序或Comparator排序
- 基本操作O(log n)
示例:
Map<String, Integer> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
map.put("B", 2);
map.put("a", 1); // 不区分大小写
// 顺序为{a=1, B=2}
五、Queue/Deque接口及实现类
1. PriorityQueue
特点:
- 基于优先级堆(通常是最小堆)
- 不允许null元素
- 元素必须实现Comparable或提供Comparator
示例:
Queue<Integer> pq = new PriorityQueue<>();
pq.offer(3); // 添加元素
pq.offer(1);
pq.offer(2);
pq.poll(); // 移除并返回头部(1)
2. ArrayDeque
特点:
- 基于循环数组实现
- 比LinkedList更高效
- 可用作栈或队列
示例:
Deque<String> deque = new ArrayDeque<>();
// 作为栈使用
deque.push("A"); // 入栈
deque.push("B");
deque.pop(); // 出栈(B)
// 作为队列使用
deque.offer("C"); // 入队
deque.poll(); // 出队(A)
六、工具类Collections
常用方法:
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 2));
Collections.sort(list); // 排序[1, 2, 3]
Collections.reverse(list); // 反转[3, 2, 1]
Collections.shuffle(list); // 随机打乱
Collections.binarySearch(list, 2); // 二分查找
Collections.max(list); // 最大值
Collections.min(list); // 最小值
Collections.replaceAll(list, 2, 4); // 替换所有2为4
// 创建不可变集合
List<Integer> unmodifiable = Collections.unmodifiableList(list);
// 创建同步集合
List<Integer> synchronizedList = Collections.synchronizedList(list);
七、Java 8+新特性
1. Stream API操作集合
List<String> list = Arrays.asList("A", "B", "C");
// 过滤
list.stream().filter(s -> s.startsWith("A")).count();
// 映射
list.stream().map(String::toLowerCase).collect(Collectors.toList());
// 排序
list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
// 分组
Map<Integer, List<String>> groupByLength =
list.stream().collect(Collectors.groupingBy(String::length));
// 统计
IntSummaryStatistics stats =
list.stream().collect(Collectors.summarizingInt(String::length));
2. Map新增方法
Map<String, Integer> map = new HashMap<>();
// 键不存在时计算值
map.computeIfAbsent("A", k -> k.length()); // A=1
// 键存在时重新计算值
map.computeIfPresent("A", (k, v) -> v + 1); // A=2
// 合并值
map.merge("A", 1, (oldVal, newVal) -> oldVal + newVal); // A=3
// 遍历
map.forEach((k, v) -> System.out.println(k + ":" + v));
八、集合使用最佳实践
- 选择合适的集合类型:
- 需要快速随机访问 → ArrayList
- 频繁插入删除 → LinkedList
- 去重 → HashSet
- 键值对 → HashMap
- 排序 → TreeSet/TreeMap
- 预估容量:构造集合时指定初始容量避免频繁扩容
- 遍历集合:
- 使用Iterator或增强for循环修改集合会抛出ConcurrentModificationException
- 需要修改时使用Iterator的remove()方法
- 线程安全:
- 使用Collections.synchronizedXXX()包装
- 或使用java.util.concurrent包下的并发集合
- 性能考虑:
- ArrayList vs LinkedList
- HashMap vs TreeMap
- HashSet vs TreeSet
- 不可变集合:
- 使用Collections.unmodifiableXXX()
- Java 9+的List.of(), Set.of(), Map.of()
掌握Java集合框架对于编写高效、可维护的Java程序至关重要。理解各种集合的实现原理和适用场景,可以帮助你在实际开发中做出最佳选择。