在 Java 8 中,对两个Set集合取交集有几种常用写法,我把性能和用法都列出来供你参考:
一、常用写法
方法一:retainAll()(原地修改)
java
Set<Long> set1 = new HashSet<>(Arrays.asList(1L, 2L, 3L, 4L)); Set<Long> set2 = new HashSet<>(Arrays.asList(3L, 4L, 5L, 6L)); set1.retainAll(set2); // set1 被修改,变成 {3, 4} System.out.println(set1); // [3, 4]特点:
✅ 效率高(内部优化)
⚠️ 会修改原集合
set1,原数据丢失如果不想破坏原集合,先复制一份再操作
方法二:Stream.filter()(不修改原集合)
java
Set<Long> set1 = new HashSet<>(Arrays.asList(1L, 2L, 3L, 4L)); Set<Long> set2 = new HashSet<>(Arrays.asList(3L, 4L, 5L, 6L)); Set<Long> intersection = set1.stream() .filter(set2::contains) .collect(Collectors.toSet()); System.out.println(intersection); // [3, 4]
特点:
✅ 不修改原集合
⚠️ 在大数据量下性能稍低于
retainAll
方法三:new HashSet<>(set1)+retainAll()(不破坏原集合)
java
Set<Long> intersection = new HashSet<>(set1); // 复制 intersection.retainAll(set2); // 取交集 System.out.println(intersection); // [3, 4]
特点:
✅ 不修改原集合
✅ 性能优秀(接近
retainAll)推荐用于需要保留原集合的场景
方法四:SetUtils.intersection()(Apache Commons / Hutool)
java
// Hutool Set<Long> intersection = CollUtil.intersection(set1, set2); // 或者 Apache Commons Set<Long> intersection = SetUtils.intersection(set1, set2);
二、三种方式对比
| 方式 | 修改原集合 | 性能 | 推荐度 |
|---|---|---|---|
set1.retainAll(set2) | ✅ 修改 set1 | 最高 | ⭐⭐⭐(不介意修改原集合时) |
new HashSet<>(set1).retainAll(set2) | ❌ 不修改 | 高 | ⭐⭐⭐⭐⭐(推荐) |
stream().filter().collect() | ❌ 不修改 | 较高 | ⭐⭐⭐⭐(需要流式处理时) |
HutoolCollUtil.intersection() | ❌ 不修改 | 高 | ⭐⭐⭐⭐⭐(已引入 Hutool) |
三、空集合的处理
java
Set<Long> set1 = Collections.emptySet(); Set<Long> set2 = new HashSet<>(Arrays.asList(1L, 2L, 3L)); // 使用 Stream 方式,空集合安全 Set<Long> intersection = set1.stream() .filter(set2::contains) .collect(Collectors.toSet()); // 返回空集合 // 使用 retainAll 方式 Set<Long> intersection = new HashSet<>(set1); // 空集合 intersection.retainAll(set2); // 仍然是空集合,安全
四、完整示例
java
import java.util.*; public class SetIntersectionDemo { public static void main(String[] args) { Set<Long> set1 = new HashSet<>(Arrays.asList(1L, 2L, 3L, 4L, 5L)); Set<Long> set2 = new HashSet<>(Arrays.asList(4L, 5L, 6L, 7L, 8L)); // 方式一:不修改原集合(推荐) Set<Long> result1 = new HashSet<>(set1); result1.retainAll(set2); System.out.println("交集: " + result1); // [4, 5] // 方式二:使用 Stream Set<Long> result2 = set1.stream() .filter(set2::contains) .collect(Collectors.toSet()); System.out.println("交集: " + result2); // [4, 5] // 方式三:使用 Hutool Set<Long> result3 = CollUtil.intersection(set1, set2); System.out.println("交集: " + result3); // [4, 5] // 原始集合未被修改 System.out.println("set1: " + set1); // [1, 2, 3, 4, 5] System.out.println("set2: " + set2); // [4, 5, 6, 7, 8] } }五、推荐写法
| 场景 | 推荐 |
|---|---|
| 不关心原集合,追求性能 | set1.retainAll(set2) |
| 需要保留原集合 | new HashSet<>(set1).retainAll(set2) |
| 项目已引入 Hutool | CollUtil.intersection(set1, set2) |
| 需要流式处理(过滤/映射) | stream().filter().collect() |