Java 集合框架深度解析:常用类、核心方法与实战技巧
·
在 Java 编程中,集合框架(Collection Framework)是每个开发者必须掌握的核心内容。无论是处理用户输入、操作数据库结果,还是实现算法逻辑,集合类都扮演着至关重要的角色。
今天,我们将从一个简单的字符串去重排序问题出发,深入探讨 Java 集合框架的常用类、核心方法以及最佳实践,帮助你构建完整的集合知识体系。
🎯 问题引入:字符串字符去重与升序输出
需求:输入字符串 banana,输出去重后的字符并按升序排列:
a
b
n
这个问题看似简单,却涉及了集合框架中多个重要概念。让我们以此为切入点,系统梳理 Java 集合体系。
📚 Java 集合框架整体架构
Java 集合框架主要分为三大体系:
1. Collection 接口体系
- List:有序、可重复
- Set:无序(或有序)、不可重复
- Queue:队列结构
2. Map 接口体系
- 键值对存储,键不可重复
3. 工具类
Collections:集合操作工具Arrays:数组操作工具
Collection
├── List
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector
├── Set
│ ├── HashSet
│ ├── LinkedHashSet
│ └── TreeSet
└── Queue
├── PriorityQueue
└── Deque (LinkedList 实现)
Map
├── HashMap
├── LinkedHashMap
├── TreeMap
└── Hashtable
📌 一、List 接口及其实现类
ArrayList vs LinkedList
| 特性 | ArrayList | LinkedList |
|---|---|---|
| 底层结构 | 动态数组 | 双向链表 |
| 随机访问 | O(1) ⭐ | O(n) |
| 插入/删除 | O(n)(中间位置) | O(1)(已知位置)⭐ |
| 内存占用 | 较少 | 较多(存储前后指针) |
| 线程安全 | ❌ | ❌ |
常用方法
// 基础操作
list.add(E e); // 添加元素
list.add(int index, E e); // 指定位置插入
list.get(int index); // 获取指定位置元素
list.set(int index, E e); // 替换指定位置元素
list.remove(int index); // 删除指定位置元素
list.remove(Object o); // 删除第一个匹配元素
list.size(); // 获取大小
list.isEmpty(); // 是否为空
// List 特有方法
list.subList(int from, int to); // 获取子列表
Collections.sort(list); // 排序
Collections.reverse(list); // 反转
特殊方法(LinkedList)
// 作为 List 使用
linkedList.getFirst(); // 获取第一个元素
linkedList.getLast(); // 获取最后一个元素
linkedList.removeFirst(); // 删除并返回第一个元素
linkedList.removeLast(); // 删除并返回最后一个元素
linkedList.addFirst(E e); // 在开头添加
linkedList.addLast(E e); // 在末尾添加
💡 回到最初的问题:如果题目要求"使用 LinkedList 的特殊方法将首尾元素分别替换为 start 和 end",正确做法是:
linkedList.removeFirst(); linkedList.addFirst("start"); linkedList.removeLast(); linkedList.addLast("end");
📌 二、Set 接口及其实现类
三种 Set 的对比
| 实现类 | 底层结构 | 是否有序 | 是否允许 null | 时间复杂度 |
|---|---|---|---|---|
| HashSet | 哈希表 | ❌ 无序 | ✅ 允许一个 | O(1) |
| LinkedHashSet | 哈希表 + 链表 | ✅ 插入顺序 | ✅ 允许一个 | O(1) |
| TreeSet | 红黑树 | ✅ 自然排序/自定义排序 | ❌ 不允许 | O(log n) |
常用方法(所有 Set 共享)
set.add(E e); // 添加元素(去重)
set.remove(Object o); // 删除元素
set.contains(Object o); // 是否包含
set.size(); // 大小
set.isEmpty(); // 是否为空
set.clear(); // 清空
// Set 特有操作
set1.addAll(set2); // 并集
set1.retainAll(set2); // 交集
set1.removeAll(set2); // 差集
TreeSet 特有方法
treeSet.first(); // 返回第一个(最小)元素
treeSet.last(); // 返回最后一个(最大)元素
treeSet.lower(E e); // 返回小于 e 的最大元素
treeSet.higher(E e); // 返回大于 e 的最小元素
treeSet.subSet(E from, E to); // 返回子集
✅ 解决字符串去重排序问题的最佳方案:
TreeSet<Character> set = new TreeSet<>(); for (char c : input.toCharArray()) { set.add(c); }
📌 三、Map 接口及其实现类
四种 Map 的对比
| 实现类 | 底层结构 | 是否有序 | 线程安全 | null 支持 |
|---|---|---|---|---|
| HashMap | 哈希表 | ❌ 无序 | ❌ | ✅ key/value 都支持 |
| LinkedHashMap | 哈希表 + 链表 | ✅ 插入顺序/访问顺序 | ❌ | ✅ |
| TreeMap | 红黑树 | ✅ key 自然排序 | ❌ | ❌ key 不支持 |
| Hashtable | 哈希表 | ❌ | ✅ | ❌ |
常用方法
map.put(K key, V value); // 添加/更新键值对
map.get(Object key); // 获取值
map.remove(Object key); // 删除键值对
map.containsKey(Object key); // 是否包含键
map.containsValue(Object value); // 是否包含值
map.size(); // 大小
map.isEmpty(); // 是否为空
map.clear(); // 清空
// 遍历方式
for (Map.Entry<K, V> entry : map.entrySet()) {
K key = entry.getKey();
V value = entry.getValue();
}
// Java 8+ 新方法
map.forEach((k, v) -> System.out.println(k + "=" + v));
map.computeIfAbsent(key, k -> defaultValue); // 不存在时计算并添加
map.merge(key, value, (oldVal, newVal) -> oldVal + newVal); // 合并操作
📌 四、集合构造函数详解
集合到集合的转换
// List 构造函数
List<E> list = new ArrayList<>(collection);
// Set 构造函数
Set<E> set = new HashSet<>(collection);
Set<E> sortedSet = new TreeSet<>(collection);
// Map 构造函数
Map<K, V> map = new HashMap<>(map2);
构造函数签名
// ArrayList
public ArrayList(Collection<? extends E> c)
// HashSet
public HashSet(Collection<? extends E> c)
// TreeSet - 注意:要求元素可比较
public TreeSet(Collection<? extends E> c)
⚠️ 重要限制:
TreeSet的构造函数要求传入的集合中所有元素都实现了Comparable接口,或者你在创建TreeSet时提供了Comparator。
泛型兼容性
✅ 正确示例:
Set<Character> charSet = new HashSet<>();
List<Character> charList = new ArrayList<>(charSet); // ✅ 完全兼容
Set<String> stringSet = new HashSet<>();
List<Object> objList = new ArrayList<>(stringSet); // ✅ String 是 Object 的子类
❌ 错误示例:
Set<String> stringSet = new HashSet<>();
List<Integer> intList = new ArrayList<>(stringSet); // ❌ 编译错误!
📌 五、Collections 工具类常用方法
Collections 类提供了大量静态方法来操作集合:
// 排序相关
Collections.sort(list); // 自然排序
Collections.sort(list, comparator); // 自定义排序
Collections.reverse(list); // 反转
// 查找相关
Collections.max(collection); // 最大值
Collections.min(collection); // 最小值
Collections.frequency(collection, obj); // 元素出现次数
// 不可变集合
Collections.unmodifiableList(list); // 返回不可修改的视图
Collections.emptyList(); // 返回空列表
// 同步集合(线程安全)
Collections.synchronizedList(list); // 返回线程安全的包装
// 其他实用方法
Collections.shuffle(list); // 随机打乱
Collections.fill(list, obj); // 填充相同元素
Collections.replaceAll(list, oldVal, newVal); // 批量替换
🧪 实战案例:完整解决方案
结合我们学到的所有知识,来看几个完整的实战案例。
案例1:字符串字符去重排序(原问题)
import java.util.*;
public class StringProcessor {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String input = in.next();
// 方案1:TreeSet(推荐)
TreeSet<Character> sortedUniqueChars = new TreeSet<>();
for (char c : input.toCharArray()) {
sortedUniqueChars.add(c);
}
sortedUniqueChars.forEach(System.out::println);
// 方案2:HashSet + 排序
Set<Character> uniqueChars = new HashSet<>();
for (char c : input.toCharArray()) {
uniqueChars.add(c);
}
List<Character> sortedList = new ArrayList<>(uniqueChars);
Collections.sort(sortedList);
sortedList.forEach(System.out::println);
}
}
案例2:统计字符频率
// 使用 Map 统计字符出现次数
Map<Character, Integer> charCount = new HashMap<>();
for (char c : input.toCharArray()) {
charCount.merge(c, 1, Integer::sum);
}
// 按字符排序输出
new TreeMap<>(charCount).forEach((k, v) ->
System.out.println(k + ": " + v));
案例3:去重并保持插入顺序
// 使用 LinkedHashSet 保持插入顺序
Set<Character> orderedUnique = new LinkedHashSet<>();
for (char c : input.toCharArray()) {
orderedUnique.add(c);
}
orderedUnique.forEach(System.out::println);
// 输入 "banana" 输出: b, a, n
🚀 性能建议与最佳实践
1. 选择合适的集合类型
- 需要快速查找 →
HashSet/HashMap - 需要排序 →
TreeSet/TreeMap - 需要保持插入顺序 →
LinkedHashSet/LinkedHashMap - 频繁在两端操作 →
LinkedList - 随机访问为主 →
ArrayList
2. 初始化容量
// 避免频繁扩容
List<String> list = new ArrayList<>(expectedSize);
Map<String, Integer> map = new HashMap<>(expectedSize);
3. 使用泛型
// ✅ 好的做法
List<String> list = new ArrayList<>();
// ❌ 避免原始类型
List list = new ArrayList();
4. 面向接口编程
// ✅ 推荐:依赖抽象
List<String> list = new ArrayList<>();
// ⚠️ 谨慎:依赖具体实现
ArrayList<String> list = new ArrayList<>();
5. 不可变集合(Java 9+)
// 创建不可变集合
List<String> immutableList = List.of("a", "b", "c");
Set<String> immutableSet = Set.of("x", "y", "z");
Map<String, Integer> immutableMap = Map.of("key", 1, "key2", 2);
🔚 总结
Java 集合框架是一个强大而灵活的工具箱,掌握其核心类和方法能够让你写出更高效、更优雅的代码。
| 场景 | 推荐集合 | 理由 |
|---|---|---|
| 去重 + 升序 | TreeSet |
自动排序,代码简洁 |
| 去重 + 插入顺序 | LinkedHashSet |
保持元素插入顺序 |
| 高频随机访问 | ArrayList |
O(1) 访问性能 |
| 频繁头尾操作 | LinkedList |
O(1) 头尾插入删除 |
| 键值对存储 | HashMap |
最佳平均性能 |
| 键值对排序 | TreeMap |
按键自动排序 |
通过本文的学习,你应该能够:
- 理解各种集合类的特点和适用场景
- 熟练使用集合的构造函数进行类型转换
- 运用
Collections工具类简化操作 - 根据具体需求选择最合适的集合实现
集合框架是 Java 编程的基础,也是面试中的高频考点。希望这篇详细的解析能帮助你在实际开发中更加得心应手!
互动时间:你在项目中遇到过哪些集合相关的性能问题?欢迎在评论区分享你的经验和解决方案!
更多推荐



所有评论(0)