Set集合接口
• 查:int size()(返回元素个数)、boolean isEmpty()(判断是否为空)、boolean contains(Object o)(判断是否含指定元素,依赖 equals/hashCode 或排序规则);• 存储自定义对象(如 User、Student)时,必须同时重写对象的 hashCode() 和 equals() 方法,否则无法正确去重(默认用 Object 类的地址比较
一、Set 核心定义
Set 是 Java 单列集合 Collection 的核心子接口(非类),定义「无序、不可重复、无索引」的单列集合规范,仅存储独立元素,自动去重,无法通过索引操作元素,需通过实现类落地功能。
二、Set 核心特性
1. 不可重复性:集合中不允许存储值相等的元素(自动去重,去重规则由实现类决定);
2. 无序性:元素存储顺序与遍历顺序不一定一致(LinkedHashSet 除外,保留插入顺序);
3. 无索引:不支持整数索引访问/操作元素,无法用普通 for 循环遍历;
4. 继承 Collection 特性:支持泛型、动态扩容、通用增删查遍历方法,默认实现类均非线程安全;
5. 可空性:HashSet/LinkedHashSet 允许存储 1 个 null 元素,TreeSet 不允许存储 null 元素。
三、Set 核心实现类(3个必掌握)
1. HashSet(最常用,无序去重)
• 去重规则:依赖元素的 hashCode() 和 equals() 方法(核心重点):
1. 先调用元素的 hashCode() 计算存储位置;
2. 若位置为空,直接存入元素;
3. 若位置非空,调用 equals() 对比元素:相等则去重(不存入),不相等则处理哈希冲突后存入;
• 性能:查询、增删效率高(时间复杂度 O(1)),无序;
• 线程安全:非线程安全;
• 适用场景:无需保证顺序,仅需快速去重的场景(如存储不重复的用户 ID、手机号)。
2. LinkedHashSet(有序去重)
• 底层实现:「哈希表 + 双向链表」(基于 HashSet 扩展,链表记录元素插入顺序);
• 核心优势:兼具 HashSet 的快速去重/高效操作,同时保留元素「插入顺序」(遍历顺序 = 插入顺序);
• 去重规则:与 HashSet 一致(依赖 hashCode() 和 equals());
• 性能:效率略低于 HashSet(多了链表维护顺序的开销),有序;
• 线程安全:非线程安全;
• 适用场景:需要去重且需保留插入顺序的场景(如按添加顺序存储唯一的操作记录)。
四、Set 核心方法(继承 + 特有)
继承 Collection 的通用方法(核心常用)
• 增:boolean add(E e)(添加元素,重复则返回 false,不存入)、boolean addAll(Collection<? extends E> c)(添加另一个集合元素,自动去重);
• 删:boolean remove(Object o)(删除指定元素,成功返回 true)、void clear()(清空集合);
• 查:int size()(返回元素个数)、boolean isEmpty()(判断是否为空)、boolean contains(Object o)(判断是否含指定元素,依赖 equals/hashCode 或排序规则);
• 转换:Object[] toArray()、<T> T[] toArray(T[] a)(转为指定类型数组)。
五、Set 遍历方式(2种,无普通 for 循环)
1. 迭代器遍历(最安全,支持遍历中删除)
Set<String> set = new HashSet<>();
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String elem = iterator.next();
// 遍历中删除元素(必须用 iterator.remove(),避免并发修改异常)
if (elem.equals("无效值")) {
iterator.remove();
}
}
2. 增强 for 循环(简洁,不支持遍历中删除)
for (String elem : set) {
System.out.println(elem);
}
六、Set 去重/排序关键注意事项
1. HashSet/LinkedHashSet 去重(必重写 2 个方法)
• 存储自定义对象(如 User、Student)时,必须同时重写对象的 hashCode() 和 equals() 方法,否则无法正确去重(默认用 Object 类的地址比较,相同对象不同地址会被视为不同元素);
• 重写原则:equals() 返回 true 时,hashCode() 必须返回相同值;hashCode() 不同时,equals() 必须返回 false(保证逻辑一致)。
七、Set 实现类选择依据
1. 优先选 HashSet:无需顺序,仅需快速去重(性能最优,日常开发最常用);
2. 选 LinkedHashSet:需要去重 + 保留插入顺序(略牺牲性能换有序);
一句话总结:Set 是「无序/有序、不可重复、无索引」的单列集合,核心能力是去重(+ 排序),关键掌握实现类的底层结构和去重/排序规则
八、代码
1.
package testset;
import java.util.HashSet;
import java.util.Set;
public class TestSet1 {
public static void main(String[] args) {
//利用set集合添加多个字符串
Set<String> strs=new HashSet<>();
String s1=new String ("hello");
String s2=new String ("world");
String s3=new String ("java");
String s4=new String ("java");
System.out.println(s3==s4);
System.out.println(s3.equals(s4));
strs.add(s1);
strs.add(s2);
strs.add(s3);
strs.add(s4);
//
for(String s:strs){
System.out.println(s);
}
2.
package testset;
import java.util.HashSet;
import java.util.Set;
public class TestSet2 {
public static void main(String[] args) {
Set<Student> set=new HashSet<>();
Student s1=new Student("小李",29,99.8);
Student s2=new Student("小红",18,95.8);
Student s3=new Student("小黄",38,65.0);
Student s4=new Student("小黄",38,65.0);
System.out.println(s3==s4);//false
System.out.println(s3.equals(s4));
set.add(s1);
set.add(s2);
set.add(s3);
for(Student s:set){
System.out.println(s);
}
}
}
更多推荐



所有评论(0)