Set的使用与代码题常见场景
一、Set是什么?
Set是Java集合框架中的接口(java.util.Set
),表示不包含重复元素的集合。核心特点:
- 元素唯一性(自动去重)
- 无序性(除
LinkedHashSet
和TreeSet
外) - 允许一个
null
元素 常用实现类:
HashSet
:基于哈希表,最快查询LinkedHashSet
:保持插入顺序TreeSet
:基于红黑树,自动排序
二、解决什么问题
- 去重需求:自动过滤重复元素
- 快速存在性检查:高效判断元素是否存在(
O(1)
时间复杂度) - 集合运算:交集、并集、差集等操作
- 无序唯一集合:不需要索引的场景
三、核心方法
java
// 常用方法
boolean add(E e) // 添加元素(重复返回false)
boolean contains(Object o) // 检查存在性
boolean remove(Object o) // 删除元素
int size() // 元素数量
boolean isEmpty() // 判空
void clear() // 清空集合
// JDK8+新增
boolean removeIf(Predicate<? super E> filter) // 条件删除
Spliterator<E> spliterator() // 并行遍历
四、应用场景(代码题高频)
去重操作
javaList<Integer> list = Arrays.asList(1, 2, 2, 3, 4, 4); Set<Integer> uniqueSet = new HashSet<>(list); // 自动去重 System.out.println(uniqueSet); // [1, 2, 3, 4]
存在性检查
javaSet<String> dictionary = new HashSet<>(Arrays.asList("apple", "banana")); System.out.println(dictionary.contains("apple")); // true
统计不同元素数量
javaString text = "hello world"; long charCount = text.chars().distinct().count(); // JDK8流式API
集合运算(交集/并集/差集)
javaSet<Integer> setA = new HashSet<>(Arrays.asList(1, 2, 3)); Set<Integer> setB = new HashSet<>(Arrays.asList(3, 4, 5)); // 交集 setA.retainAll(setB); // setA变为[3] // 并集 setA.addAll(setB); // setA变为[1,2,3,4,5] // 差集 setA.removeAll(setB); // 移除setB中的元素
字母异位词检查
javaboolean isAnagram(String s1, String s2) { return Arrays.equals( s1.chars().sorted().toArray(), s2.chars().sorted().toArray() ); }
五、不同Set实现对比
特性 | HashSet | LinkedHashSet | TreeSet |
---|---|---|---|
顺序 | 无序 | 插入顺序 | 自然排序 |
性能 | O(1) | O(1) | O(log n) |
排序支持 | 否 | 否 | 是 |
线程安全 | 否 | 否 | 否 |
六、重要注意事项
重写hashCode()和equals()
- 自定义对象放入Set需正确重写这两个方法
javaclass Student { String id; // 必须重写 @Override public int hashCode() { return id.hashCode(); } @Override public boolean equals(Object o) { /*...*/ } }
TreeSet排序规则
- 元素需实现
Comparable
接口,或创建时传入Comparator
javaSet<Integer> sortedSet = new TreeSet<>((a, b) -> b - a); // 降序
- 元素需实现
线程安全问题
- 非线程安全,多线程环境用:
javaSet<Object> safeSet = Collections.synchronizedSet(new HashSet<>());
JDK9+工厂方法
javaSet<String> fastSet = Set.of("A", "B", "C"); // 不可变集合
七、总结
在代码题中优先考虑Set:
- 需要去重时 → 首选
HashSet
- 需要保持插入顺序 →
LinkedHashSet
- 需要自动排序 →
TreeSet
- 高频操作:存在性检查(
contains()
)、集合运算(addAll
/removeAll
)
最佳实践:
- 大数据量去重用
HashSet
- 需要顺序访问用
LinkedHashSet
- 范围查询(如找最大/最小值)用
TreeSet
- JDK8+优先使用Stream API配合Set操作