在 Java 集合框架中,Set
是一种不允许重复元素且不保证顺序(部分实现类会维护顺序)的集合。以下是其核心特点及常见实现类的详细说明:
Set 集合的核心特点
-
唯一性
-
集合中不允许存在重复元素(通过
equals()
和hashCode()
方法判断重复性)。 -
添加重复元素时,操作会被忽略(返回
false
)。
-
-
无序性
-
默认不保证元素的存储顺序(如
HashSet
)。 -
部分实现类支持有序性(如
TreeSet
按自然排序,LinkedHashSet
按插入顺序)。
-
-
允许
null
值-
大多数实现类允许一个
null
元素(但TreeSet
不允许,因为依赖排序规则)。
-
-
非线程安全
-
常见实现类(如
HashSet
、TreeSet
)非线程安全,需自行同步或使用并发集合。
-
Set 的实现类及特性
1. HashSet
-
底层数据结构:基于 哈希表(
HashMap
实现),通过哈希值快速定位元素。 -
特点:
-
无序(不保证插入或访问顺序)。
-
允许
null
值。 -
查询效率高(
O(1)
时间复杂度),但迭代顺序不可预测。
-
-
适用场景:快速去重、无需顺序控制的场景。
Set<String> set = new HashSet<>(); set.add("Apple"); set.add("Banana"); set.add(null); // 允许 null
2. LinkedHashSet
-
底层数据结构:基于 哈希表 + 双向链表,继承自
HashSet
。 -
特点:
-
维护元素的 插入顺序(迭代顺序与插入顺序一致)。
-
允许
null
值。 -
查询效率略低于
HashSet
(因需维护链表)。
-
-
适用场景:需要去重且保留插入顺序的场景(如缓存记录顺序)。
Set<String> set = new LinkedHashSet<>(); set.add("Apple"); set.add("Banana"); set.add("Apple"); // 重复元素被忽略 // 迭代顺序:Apple → Banana
3. TreeSet
-
底层数据结构:基于 红黑树(
TreeMap
实现),自动排序。 -
特点:
-
元素按 自然顺序 或 自定义比较器(
Comparator
)排序。 -
不允许
null
值(排序依赖compareTo()
或Comparator
)。 -
增删查操作时间复杂度为
O(log n)
。
-
-
适用场景:需要元素有序且去重的场景。
Set<Integer> set = new TreeSet<>(); set.add(5); set.add(2); set.add(8); // 自动排序结果:2 → 5 → 8
4. CopyOnWriteArraySet
(并发安全)
-
底层数据结构:基于 动态数组 + 写时复制(Copy-On-Write)机制。
-
特点:
-
线程安全,适用于读多写少的场景。
-
每次修改操作(增、删)会复制底层数组,性能较低。
-
迭代器遍历的是创建时的快照,不会抛出
ConcurrentModificationException
。
-
-
适用场景:高并发环境下的读操作远多于写操作的集合。
性能对比
实现类 | 底层结构 | 顺序性 | 允许 null | 时间复杂度(增删查) | 线程安全 |
---|---|---|---|---|---|
HashSet | 哈希表 | 无序 | ✔️ | O(1) | ❌ |
LinkedHashSet | 哈希表+链表 | 插入顺序 | ✔️ | O(1) | ❌ |
TreeSet | 红黑树 | 自然/自定义 | ❌ | O(log n) | ❌ |
CopyOnWriteArraySet | 数组 | 插入顺序 | ✔️ | O(n)(写操作) | ✔️ |
选择建议
-
快速去重且无需顺序 →
HashSet
。 -
保留插入顺序的去重 →
LinkedHashSet
。 -
需要元素排序 →
TreeSet
。 -
高并发读操作 →
CopyOnWriteArraySet
(谨慎用于写多场景)。
注意事项
-
所有
Set
实现类依赖元素的equals()
和hashCode()
方法判断重复性,需正确重写这两个方法。 -
TreeSet
若未指定Comparator
,元素必须实现Comparable
接口,否则抛出ClassCastException
。