Set 接口与实现
Set 是 Collection 的子接口,表示不重复元素的集合。
Set 接口特点
| 特性 | 说明 |
|---|---|
| 不重复 | 不允许存储重复元素 |
| 无序(部分) | HashSet 无序,LinkedHashSet/TreeSet 有序 |
| 可null | HashSet/LinkedHashSet 允许一个 null,TreeSet 不允许 |
Set 核心方法
Java
// 添加(重复元素不会被添加)
set.add(element); // 添加元素,返回是否成功
// 删除
set.remove(element); // 删除元素
set.clear(); // 清空
// 判断
set.contains(element); // 是否包含元素
set.isEmpty(); // 是否为空
set.size(); // 元素数量
// 遍历
set.iterator(); // 获取迭代器
set.forEach(System.out::println); // 函数式遍历
HashSet
特点
- 基于 HashMap 实现
- 无序:元素顺序不确定
- 查询/插入/删除:O(1)
- 允许一个 null
使用示例
Java
Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("A"); // 重复,不会被添加,返回 false
System.out.println(set); // 输出顺序不确定:[B, A]
set.contains("A"); // true
set.remove("B"); // 删除成功
重复判断:通过 equals() 和 hashCode() 判断重复。自定义对象需正确实现这两个方法。
LinkedHashSet
特点
- HashSet 的子类
- 有序:按插入顺序排列
- 维护双向链表记录插入顺序
- 性能略低于 HashSet
使用示例
Java
Set<String> set = new LinkedHashSet<>();
set.add("A");
set.add("B");
set.add("C");
System.out.println(set); // 输出:[A, B, C](按插入顺序)
适用场景:需要去重且保持插入顺序的场景。
TreeSet
特点
- 基于 TreeMap(红黑树)实现
- 自然排序:元素按自然顺序排列
- 查询/插入/删除:O(log n)
- 不允许 null
使用示例
Java
// 自然排序(元素需实现 Comparable)
Set<Integer> set = new TreeSet<>();
set.add(3);
set.add(1);
set.add(2);
System.out.println(set); // [1, 2, 3](排序后)
// 自定义排序(Comparator)
Set<String> set = new TreeSet<>(Comparator.reverseOrder());
set.add("A");
set.add("B");
set.add("C");
System.out.println(set); // [C, B, A](降序)
// TreeSet 特有方法
TreeSet<Integer> ts = new TreeSet<>();
ts.first(); // 最小元素
ts.last(); // 最大元素
ts.lower(5); // 小于 5 的最大元素
ts.higher(5); // 大于 5 的最小元素
ts.headSet(5); // 小于 5 的元素集合
ts.tailSet(5); // 大于等于 5 的元素集合
HashSet vs LinkedHashSet vs TreeSet
| 特性 | HashSet | LinkedHashSet | TreeSet |
|---|---|---|---|
| 顺序 | 无序 | 插入顺序 | 自然排序 |
| 性能 | O(1)最快 | O(1)略慢 | O(log n) |
| null | 允许 | 充许 | 不允许 |
| 适用场景 | 一般去重 | 去重+保持顺序 | 去重+排序 |
自定义对象存入 Set
Java
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person p = (Person) obj;
return age == p.age && Objects.equals(name, p.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
Set<Person> set = new HashSet<>();
set.add(new Person("张三", 25));
set.add(new Person("张三", 25)); // 重复,不会添加
必须实现 equals() 和 hashCode():否则HashSet/LinkedHashSet 无法正确判断重复。
要点总结
- Set:不重复元素的集合
- HashSet:无序,性能最高 O(1)
- LinkedHashSet:有序(插入顺序),性能略低
- TreeSet:自然排序,性能 O(log n)
- 自定义对象需实现 equals() 和 hashCode()
- TreeSet 不允许 null,元素需实现 Comparable 或提供 Comparator
- 选择原则:一般去重用 HashSet,有序用 LinkedHashSet,排序用 TreeSet
📝 发现内容有误?点击此处直接编辑