当前位置: 首页 > news >正文

Java Set 集合详解:从基础语法到实战应用,彻底掌握去重与唯一性集合

作为一名 Java 开发工程师,你一定在实际开发中遇到过需要去重、唯一性校验、快速查找等场景。这时候,Set 集合 就成为你不可或缺的工具。

本文将带你全面掌握:

  • Set 接口的定义与核心方法
  • 常见实现类(如 HashSetTreeSetLinkedHashSet
  • Set 的去重原理(equals() 与 hashCode()
  • Set 的遍历、增删查改、集合运算(交集、并集、差集)
  • Set 在实际业务中的应用场景
  • 线程安全与并发使用的最佳实践

并通过丰富的代码示例和真实项目场景讲解,帮助你写出更高效、结构更清晰的 Java 集合代码。


🧱 一、什么是 Set 集合?

Set 是 Java 集合框架中 Collection 接口的子接口之一,它表示一个不包含重复元素的集合。

✅ Set 的核心特性:

特性描述
不允许重复元素不能重复(通过 equals() 和 hashCode() 判断)
无序默认不保证插入顺序(LinkedHashSet 除外)
无索引访问不能通过索引获取元素
支持泛型推荐使用泛型来保证类型安全
适用于唯一性操作如去重、集合运算、快速查找等

🔍 二、Set 的常见实现类

实现类特点适用场景
HashSet基于哈希表实现,无序,查找快默认唯一性集合
LinkedHashSet哈希表 + 双向链表,保持插入顺序保持顺序的唯一集合
TreeSet基于红黑树实现,自动排序需要排序的唯一集合
ConcurrentSkipListSet线程安全,基于跳表实现高并发下排序集合

🧠 三、Set 的基本操作

✅ 1. 创建与初始化

// 使用 HashSet 初始化
Set<String> set = new HashSet<>();// 静态初始化
Set<String> set2 = new HashSet<>(Arrays.asList("Java", "Python", "C++"));// 不可变集合(Java 9+)
Set<String> set3 = Set.of("A", "B", "C");

✅ 2. 添加元素

set.add("Java");            // 添加元素
set.add("Java");            // 不会重复添加
set.addAll(Arrays.asList("Python", "JavaScript")); // 添加集合

✅ 3. 删除元素

set.remove("Java");         // 删除指定元素
set.clear();                // 清空集合

✅ 4. 查询元素

boolean contains = set.contains("Java"); // 是否包含某个元素
int size = set.size();      // 获取集合大小
boolean isEmpty = set.isEmpty(); // 是否为空

✅ 5. 遍历方式对比

遍历方式示例特点
增强 for 循环for (String s : set)简洁易读
Iterator 迭代器Iterator<String> it = set.iterator(); while (it.hasNext())支持在遍历中删除
Stream 流式处理set.stream().forEach(System.out::println)支持过滤、映射、排序等操作

🔁 四、Set 的高级操作

✅ 1. 集合运算(交集、并集、差集)

Set<String> set1 = new HashSet<>(Arrays.asList("A", "B", "C"));
Set<String> set2 = new HashSet<>(Arrays.asList("B", "C", "D"));// 并集
Set<String> union = new HashSet<>(set1);
union.addAll(set2);// 交集
Set<String> intersection = new HashSet<>(set1);
intersection.retainAll(set2);// 差集
Set<String> difference = new HashSet<>(set1);
difference.removeAll(set2);

✅ 2. 排序(使用 TreeSet

Set<String> sortedSet = new TreeSet<>();
sortedSet.addAll(Arrays.asList("Banana", "Apple", "Orange"));// 输出顺序:Apple, Banana, Orange

✅ 3. 保持插入顺序(使用 LinkedHashSet

Set<String> orderedSet = new LinkedHashSet<>();
orderedSet.add("First");
orderedSet.add("Second");
orderedSet.add("Third");// 遍历时顺序不变

✅ 4. 转换为 List 或数组

List<String> list = new ArrayList<>(set);
String[] array = set.toArray(new String[0]);

🧪 五、Set 的实际应用场景

场景1:去重处理(最常见用途)

List<String> duplicates = Arrays.asList("a", "b", "a", "c");
Set<String> unique = new HashSet<>(duplicates); // {"a", "b", "c"}

场景2:权限校验(判断是否包含权限)

Set<String> permissions = new HashSet<>(Arrays.asList("read", "write", "admin"));if (permissions.contains("delete")) {// 执行删除操作
}

场景3:数据同步与差异检测(如数据库对比)

Set<String> dbUsers = getFromDB(); // 数据库中的用户
Set<String> fileUsers = getFromFile(); // 文件中的用户Set<String> toAdd = new HashSet<>(fileUsers);
toAdd.removeAll(dbUsers); // 需要新增的用户Set<String> toRemove = new HashSet<>(dbUsers);
toRemove.removeAll(fileUsers); // 需要删除的用户

场景4:使用 TreeSet 实现自动排序的去重集合

Set<Integer> numbers = new TreeSet<>();
numbers.addAll(Arrays.asList(5, 3, 8, 1, 3));
// 输出顺序:1, 3, 5, 8

场景5:线程安全的 Set(多线程环境)

Set<String> safeSet = Collections.synchronizedSet(new HashSet<>());// 或使用并发集合
Set<String> concurrentSet = new CopyOnWriteArraySet<>();

🚫 六、常见误区与注意事项

误区正确做法
忘记重写 equals() 和 hashCode()自定义类作为 Set 元素时必须重写
使用 == 比较字符串使用 equals() 或 Objects.equals()
在遍历中直接删除元素使用 Iterator.remove()
忘记初始化 Set 就使用先 new HashSet<>()
忽略线程安全问题多线程使用 CopyOnWriteArraySet 或同步包装
错误使用 Set.of() 修改列表Set.of(...) 是不可变集合,修改会抛出异常

🧱 七、Set 与 List 的区别对比

对比项SetList
是否允许重复不允许允许
是否有序不保证顺序(LinkedHashSet 除外)有序
是否支持索引访问不支持支持
是否适合去重非常适合不适合
常用实现类HashSetTreeSetLinkedHashSetArrayListLinkedList

📊 八、总结:Java Set 核心知识点一览表

内容说明
接口定义Set<E>
常用实现类HashSetTreeSetLinkedHashSetCopyOnWriteArraySet
核心方法add、remove、contains、size、isEmpty、iterator
遍历方式增强 for、Iterator、Stream
高级操作集合运算、排序、保持顺序、去重
线程安全Collections.synchronizedSet()CopyOnWriteArraySet
应用场景去重、权限控制、数据同步、集合运算

📎 九、附录:Set 常用技巧速查表

技巧示例
创建只读集合Collections.unmodifiableSet(set)
同步集合Collections.synchronizedSet(new HashSet<>())
集合转数组set.toArray(new String[0])
判断是否为空set.isEmpty()
获取最大最小值Collections.max(set) / Collections.min(set)(需为 SortedSet
使用 Stream 过滤set.stream().filter(s -> s.startsWith("A")).toList()
使用 Stream 转换set.stream().map(String::toUpperCase).toList()
使用 Stream 收集到 Setlist.stream().collect(Collectors.toSet())
判断是否是子集set1.containsAll(set2)
集合交集set1.retainAll(set2)

如果你正在准备一篇面向初学者的技术博客,或者希望系统回顾 Java 基础知识,这篇文章将为你提供完整的知识体系和实用的编程技巧。

欢迎点赞、收藏、转发,也欢迎留言交流你在实际项目中遇到的 Set 集合相关问题。我们下期再见 👋

📌 关注我,获取更多Java核心技术深度解析!

http://www.xdnf.cn/news/1140517.html

相关文章:

  • Pythonday17
  • 群晖中相册管理 immich大模型的使用
  • C++ :vector的介绍和使用
  • MyBatis:配置文件完成增删改查_添加
  • 【RAG实战】用户反馈如何关联算法优化
  • Redisson 分布式锁
  • 构建智能客服Agent:从需求分析到生产部署
  • 使用 jar -xvf 解压JAR文件无反应怎么办?
  • 打车代驾 app 订单管理系统模块搭建
  • IDEA高效开发:Database Navigator插件安装与核心使用指南
  • Android studio和gradle升级后的一些错误
  • 进阶向:智能图像增强系统
  • 零售快销行业中线下巡店AI是如何颠覆传统计算机视觉识别的详细解决方案
  • Python爬虫入门到实战(3)-对网页进行操作
  • Linux 定时任务全解析:atd 与 crond 的区别及实战案例(含日志备份 + 时间写入)
  • 黑马Node.js全套入门教程,nodejs新教程含es6模块化+npm+express+webpack+promise等_ts对象笔记
  • 【问题解决】npm包下载速度慢
  • AI与BI的融合挑战:Strategy平台的差异化优势
  • 小白学Python,网络爬虫篇(2)——selenium库
  • (5)颜色的灰度,亮度,对比度,透明度,都啥意思
  • 零基础入门:用按键精灵实现视频自动操作(附完整脚本)
  • Instagram千号矩阵:亚矩阵云手机破解设备指纹检测的终极方案
  • 安全加固Linux内核参数对容器平台的影响评估
  • 《5分钟开发订单微服务!飞算JavaAI实战:IDEA插件安装→空指针修复→K8s部署全流程》
  • 《python语言程序设计》2018版第8章8题编写函数实现二进制转十进制(字符串变整数)!!整数没法进行下标
  • Paimon 动态分桶
  • 深入理解Java中的Map.Entry接口
  • 力扣每日一题--2025.7.17
  • 五分钟学会大数定律【笔记】
  • VOTE:基于轨迹集成投票的视觉-语言-动作模型优化