Java中HashSet求交集最直接方法是retainAll(),但会修改原集合;推荐用Stream.filter或手动遍历小集合以避免副作用,并注意自定义对象需重写equals和hashCode。

Java 中 HashSet 求两个集合交集最直接的方法是调用 retainAll() 方法,它会修改原集合,只保留与指定集合共有的元素。
使用 retainAll() 获取交集(会修改原集合)
该方法就地操作,执行后第一个集合变为交集结果。注意:原始集合内容会被改变。
- 确保其中一个集合是可修改的(不能是
Collections.unmodifiableSet()或 Stream 生成的不可变集合) - 推荐对副本调用,避免意外修改原始数据
- 示例:
HashSet<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c"));
HashSet<String> set2 = new HashSet<>(Arrays.asList("b", "c", "d"));
// 创建副本,避免修改 set1
HashSet<String> intersection = new HashSet<>(set1);
intersection.retainAll(set2); // intersection 现在是 ["b", "c"]
System.out.println(intersection); // [b, c]
不修改原集合:用 stream + filter(Java 8+)
适合需要保持原始集合不变、或想链式处理的场景。返回的是新集合,类型需手动指定。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用
stream().filter(set2::contains).collect(Collectors.toSet()) - 注意:
set2::contains在大数据量时性能依赖其内部实现(HashSet 是 O(1) 平均) - 若需保持插入顺序或确定类型,可用
Collectors.toCollection(HashSet::new)
手动遍历(兼容老版本,或需精细控制)
逻辑清晰,完全可控,适用于 Android 等受限环境或需添加额外条件(如忽略大小写)。
立即学习“Java免费学习笔记(深入)”;
- 遍历较小集合,检查是否在较大集合中存在,减少 contains 调用次数
- 示例:
HashSet<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c"));
HashSet<String> set2 = new HashSet<>(Arrays.asList("b", "c", "d"));
HashSet<String> intersection = new HashSet<>();
// 遍历较小的集合提升效率
if (set1.size() <= set2.size()) {
for (String s : set1) {
if (set2.contains(s)) intersection.add(s);
}
} else {
for (String s : set2) {
if (set1.contains(s)) intersection.add(s);
}
}
注意事项
交集结果的元素必须满足 equals() 和 hashCode() 一致;自定义对象务必正确重写这两个方法,否则交集可能为空或不全。
- 空集合参与运算结果为空
-
retainAll()返回boolean:true 表示集合实际发生了变化 - 如果两个集合都很大且内存敏感,可考虑用
Stream.iterate分批处理(较少见)

















