Java中Set交并差需用retainAll、addAll、removeAll实现,但会原地修改;应先复制集合再操作,或用Guava/Stream避免副作用。

Java 中 Set 集合本身不提供直接返回新集合的交并差方法,但可通过 addAll、retainAll、removeAll 三个操作实现,关键是要理解它们会**原地修改调用者**,不能直接当成纯函数使用。
交集:取两个集合共有的元素
用 retainAll 实现,但必须先复制一份再操作,否则原始集合会被改掉:
- 创建新集合:
Set<T> intersection = new HashSet<>(setA); - 保留与 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); - 把 setB 全部加进来:
union.addAll(setB); - 结果自动去重,无需额外处理
- 如果 setA 或 setB 是空集合,该方式仍安全有效
差集:取 setA 中有、setB 中没有的元素
用 removeAll 实现,逻辑清晰但要注意方向:
立即学习“Java免费学习笔记(深入)”;
- 创建新集合:
Set<T> difference = new HashSet<>(setA); - 删掉所有在 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 循环

















