Java Set系列集合详解:HashSet、LinkedHashSet、TreeSet底层原理与使用场景
一、Set系列集合概述
1. 核心特点
- 无序性:存取顺序不一致(LinkedHashSet除外)。
- 唯一性:元素不重复。
- 无索引:无法通过索引直接访问元素,不能使用普通
for
循环遍历。
2. 常见实现类
实现类 | 特点 | 底层数据结构 |
---|---|---|
HashSet | 无序、唯一、无索引 | 哈希表(数组+链表/红黑树) |
LinkedHashSet | 有序(存取顺序一致)、唯一 | 哈希表+双向链表 |
TreeSet | 可排序(自然或自定义)、唯一 | 红黑树 |
二、Set接口常用方法
Set
继承自Collection
接口,常用方法如下:
方法 | 说明 |
---|---|
boolean add(E e) | 添加元素,成功返回true |
void clear() | 清空集合 |
boolean remove(E e) | 删除指定元素 |
`boolean contains(Object) | 判断是否包含元素 |
int size() | 返回集合元素个数 |
三、各实现类详解
1. HashSet
底层原理
- JDK8前:数组 + 链表。
- JDK8后:数组 + 链表 + 红黑树(链表长度≥8且数组长度≥64时触发转换)。
- 哈希值计算:通过重写
hashCode()
和equals()
保证元素唯一性。
扩容机制
- 默认初始容量:16。
- 加载因子:0.75(当元素数量达到容量的75%时触发扩容)。
代码示例
Set<String> set = new HashSet<>();
set.add("A");
set.add("A"); // 添加失败
System.out.println(set); // 输出无序,如 [A, B]
2. LinkedHashSet
核心特点
- 继承自
HashSet
,通过双向链表维护插入顺序。 - 性能略低于
HashSet
,但遍历效率更高。
代码示例
LinkedHashSet<String> linkedSet = new LinkedHashSet<>();
linkedSet.add("B");
linkedSet.add("A");
System.out.println(linkedSet); // 输出顺序固定为 [B, A]
3. TreeSet
排序规则
- 自然排序:元素需实现
Comparable
接口,重写compareTo()
。 - 比较器排序:创建
TreeSet
时传入Comparator
自定义规则。
代码示例
// 自然排序(按年龄升序)
TreeSet<Student> treeSet = new TreeSet<>();
treeSet.add(new Student("Tom", 20));
treeSet.add(new Student("Alice", 18));
// 输出按年龄排序:Alice(18) → Tom(20)
四、补充知识点
1. 线程安全性
HashSet
、TreeSet
、LinkedHashSet
均非线程安全。- 解决方案:使用
Collections.synchronizedSet()
包装。
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
2. 哈希冲突解决策略
- 链地址法(HashSet采用):冲突元素以链表形式存储。
- 开放寻址法:线性探测或二次探测。
3. 红黑树简介
- 一种自平衡二叉查找树,保证插入、删除、查找的时间复杂度为
O(log n)
。 - 特性:节点颜色交替、根节点为黑、叶子节点为黑、任意路径黑节点数相同。
4. 性能对比
操作 | HashSet | LinkedHashSet | TreeSet |
---|---|---|---|
插入 | O(1) | O(1) | O(log n) |
删除 | O(1) | O(1) | O(log n) |
查询 | O(1) | O(1) | O(log n) |
有序性 | 无 | 插入顺序 | 自然/自定义 |
五、应用场景总结
场景 | 推荐集合 |
---|---|
去重且无需顺序 | HashSet |
去重且保留插入顺序 | LinkedHashSet |
去重且需排序 | TreeSet |
高频查询 | HashSet |
需要线程安全 | Collections.synchronizedSet() |
六、常见面试题
-
HashSet如何保证元素唯一?
通过hashCode()
和equals()
方法:先比较哈希值,再通过equals
判断内容是否相同。 -
TreeSet两种排序方式如何选择?
- 默认使用自然排序(需实现
Comparable
)。 - 若类无法修改或需多规则排序,使用
Comparator
。
- 默认使用自然排序(需实现
-
HashSet和HashMap的关系?
HashSet
底层基于HashMap
实现,元素存储为HashMap
的键(值固定为PRESENT
占位对象)。
关注博主,获取更多Java集合框架深度解析!