java中set交并差需用retainall、addall、removeall实现,但会原地修改;应先复制集合再操作,或用guava/stream避免副作用。

Java 中 Set 集合本身不提供直接返回新集合的交并差方法,但可通过 addAll、retainAll、removeAll 三个操作实现,关键是要理解它们会**原地修改调用者**,不能直接当成纯函数使用。
交集:取两个集合共有的元素
用 retainAll 实现,但必须先复制一份再操作,否则原始集合会被改掉:
- 创建新集合:
Set<t> intersection = new HashSet(setA);</t> - 保留与 setB 共有的部分:
intersection.retainAll(setB); - 注意:
retainAll返回 boolean 表示“是否发生实际变更”,不是“是否有交集”。判断交集是否为空应改用!Collections.disjoint(setA, setB) - 自定义对象参与运算时,务必重写
equals()和hashCode(),否则交集永远为空
并集:合并两个集合的所有不重复元素
用 addAll 实现,同样需避免污染原集合:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 创建新集合:
Set<t> union = new HashSet(setA);</t> - 把 setB 全部加进来:
union.addAll(setB); - 结果自动去重,无需额外处理
- 如果 setA 或 setB 是空集合,该方式仍安全有效
差集:取 setA 中有、setB 中没有的元素
用 removeAll 实现,逻辑清晰但要注意方向:
- 创建新集合:
Set<t> difference = new HashSet(setA);</t> - 删掉所有在 setB 中出现的元素:
difference.removeAll(setB); - 这是 A − B(A 对 B 的差),不是对称差;如需对称差,可组合两次差集或用 Stream 过滤
- 若想获取 B − A,只需交换参数顺序:用
new HashSet(setB)再调removeAll(setA)
更安全的替代方案
如果项目已引入 Guava,可用 Sets.intersection()、Sets.union()、Sets.difference(),它们都返回不可修改视图,不改动原始数据。或者用 Java 8 Stream 手写(适合小数据量或需链式处理):
- 交集:
setA.stream().filter(setB::contains).collect(Collectors.toSet()) - 差集:
setA.stream().filter(x -> !setB.contains(x)).collect(Collectors.toSet()) - 性能上,Set 的
contains是 O(1),整体为 O(n),优于双层 for 循环
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










