当前位置: 首页 > 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.lryc.cn/news/592305.html

相关文章:

  • 基于K8s ingress灰度发布配置
  • Docker报错:No address associated with hostname
  • 使用python读取json数据,简单的处理成元组数组
  • 内网部署yum源
  • 美团闪购最新版 mtgsig1.2
  • 从服务实例的元数据中获取配置值 vs 从本地配置文件中获取配置值
  • 4G模块 A7680发送中文短信到手机
  • IT66122替代IT66121-富利威
  • 「源力觉醒 创作者计划」_巅峰对话:文心 4.5 vs. DeepSeek / Qwen 3.0 深度解析(实战优化版)
  • 文件管理-文件控制块和索引节点
  • Java 抽象类与接口深度解析
  • 进阶数据结构:红黑树
  • 可靠消息最终一致性分布式事务解决方案
  • Web3加密货币交易:您需要知道的所有信息
  • MySql:索引,结构
  • 服务器mysql数据的简单备份脚本
  • Ansible + Shell 服务器巡检脚本
  • C#`Array`进阶
  • ChatGPT Agent技术架构探析
  • 力扣面试150(33/150)
  • 解决 IDEA 中 XML 文件的 “URI is not registered” 报错
  • 优先算法——专题九:链表
  • Logback 配置的利器:深入理解<property>与<variable>
  • 深度解析Linux文件I/O三级缓冲体系:用户缓冲区→标准I/O→内核页缓存
  • 【C语言】深入理解柔性数组:特点、使用与优势分析
  • MySQL安装包安装方法
  • Vue (Official) v3.0.2 新特性 为非类npm环境引入 globalTypesPath 选项
  • 28、鸿蒙Harmony Next开发:不依赖UI组件的全局气泡提示 (openPopup)和不依赖UI组件的全局菜单 (openMenu)、Toast
  • ModbusRTU转profibus网关与涡街液体流量计通讯读取流量计温度
  • 回归预测 | MATLAB实现SA-BP模拟退火算法优化BP神经网络多输入单输出回归预测