在Java中,Set
接口用于存储不重复元素的集合。以下是使用Set
的详细步骤及注意事项:
1. 创建Set实例
Set
是接口,需通过实现类(如HashSet
、TreeSet
、LinkedHashSet
)实例化:
Set<String> hashSet = new HashSet<>(); // 无序,基于哈希表
Set<String> treeSet = new TreeSet<>(); // 有序(自然或自定义排序),基于红黑树
Set<String> linkedHashSet = new LinkedHashSet<>(); // 保留插入顺序
2. 添加元素
使用add()
方法添加元素,重复元素会被自动过滤:
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Apple"); // 不会被添加
System.out.println(hashSet); // 输出 [Apple, Banana]
3. 检查元素存在性
使用contains()
方法检查元素是否存在:
boolean exists = hashSet.contains("Apple"); // true
4. 遍历元素
通过增强for循环或迭代器遍历:
// 增强for循环
for (String element : hashSet) {
System.out.println(element);
}
// 使用迭代器
Iterator<String> iterator = hashSet.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
5. 删除元素
-
删除单个元素:
remove(Object o)
-
清空集合:
clear()
hashSet.remove("Banana"); // 删除元素
hashSet.clear(); // 清空所有元素
6. 其他常用方法
-
获取大小:
size()
-
判断空集合:
isEmpty()
int size = hashSet.size(); // 元素数量
boolean isEmpty = hashSet.isEmpty(); // 是否为空
7. 排序与自定义顺序
使用TreeSet
实现排序:
Set<Integer> sortedSet = new TreeSet<>();
sortedSet.add(3);
sortedSet.add(1);
sortedSet.add(2);
System.out.println(sortedSet); // 输出 [1, 2, 3]
// 自定义排序(逆序)
Set<String> customSet = new TreeSet<>(Comparator.reverseOrder());
customSet.add("Apple");
customSet.add("Banana");
System.out.println(customSet); // 输出 [Banana, Apple]
8. 处理自定义对象
需正确覆盖equals()
和hashCode()
方法以确保唯一性:
class Person {
private String name;
private int age;
// 构造方法、getter、setter
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
// 使用示例
Set<Person> people = new HashSet<>();
people.add(new Person("Alice", 30));
people.add(new Person("Alice", 30)); // 视为重复,不会被添加
9. 允许null值
-
允许null:
HashSet
、LinkedHashSet
(仅一个null
元素) -
禁止null:
TreeSet
(抛NullPointerException
)
hashSet.add(null); // 允许
treeSet.add(null); // 抛出异常
10. 集合操作
-
并集:
addAll(Collection<? extends E> c)
-
交集:
retainAll(Collection<?> c)
-
差集:
removeAll(Collection<?> c)
Set<String> set1 = new HashSet<>(Arrays.asList("A", "B", "C"));
Set<String> set2 = new HashSet<>(Arrays.asList("B", "C", "D"));
set1.addAll(set2); // set1 → [A, B, C, D]
set1.retainAll(set2); // set1 → [B, C]
set1.removeAll(set2); // set1 → []
11. 线程安全
默认Set
实现非线程安全,可通过以下方式实现线程安全:
// 使用Collections工具类
Set<String> synchronizedSet = Collections.synchronizedSet(new HashSet<>());
// 使用并发容器(JUC包)
Set<String> concurrentSet = ConcurrentHashMap.newKeySet();
12. 性能对比
实现类 | 插入/删除/查询 | 顺序性 | 允许null |
---|---|---|---|
HashSet | O(1)(平均) | 无序 | 允许 |
LinkedHashSet | O(1) | 插入顺序 | 允许 |
TreeSet | O(log n) | 自然或自定义排序 | 不允许 |
总结
-
去重场景:优先选择
HashSet
。 -
需要排序:使用
TreeSet
。 -
保持插入顺序:用
LinkedHashSet
。 -
自定义对象:务必正确实现
equals()
和hashCode()
。 -
线程安全:使用
Collections.synchronizedSet()
或并发容器。